2026-04-16-0115.md
Session: 2026-04-16 01:15:26 UTC
- Session Key: agent:main:main
- Session ID: 56752861-e0c1-43d1-a2c4-eb316b5560a0
- Source: webchat
Conversation Summary
user: A new session was started via /new or /reset. Say hi briefly (1-2 sentences) and ask what the user wants to do next. If the runtime model differs from default_model in the system prompt, mention the default model in the greeting. Do not mention internal steps, files, tools, or reasoning.
[message_id: f52bef1a-4551-400a-82a1-4163d90eca04]
assistant: Hi snake — new session, ready when you are. What do you want to do next?
user: the skills page on my openclaw dashboard, i'm geetting - Couldn't run openclaw skills check: spawn /home/ubuntu/.npm-global/bin/openclaw ENOENT\ [message_id: b810a444-dac2-44f5-be37-cdba8514de9c]
assistant: That error was coming from the dashboard runtime not being able to refresh its cached “skills overview”, so it kept serving a stale result that said spawn ... ENOENT.
Two things were wrong:
- The Skills page / API route were eligible to run during
next build(where theopenclawbinary may not exist), so the build could “bake in” an ENOENT. - Your deployed release under
/opt/openclaw-dashboard/releases/...was owned by a different UID, so Next.js couldn’t write to.next/cache(you may have seenEACCESin logs). That prevented revalidation/refresh, so the old error stuck around.
I’ve fixed both on the server:
- Marked
/skillsand/api/skills/overviewas dynamic so they won’t run at build time. - Chowned the active release so the running service (user
ubuntu) can write its cache. - Restarted
openclaw-dashboard.service.
Now /api/skills/overview is returning real data again (it’s listing installed skills + running openclaw skills check successfully).
Can you refresh the dashboard Skills page (hard refresh) and confirm the error is gone?
If you want, I can also patch the dashboard update/deploy script to automatically chown new releases after pulling/building so this doesn’t regress on the next auto-update.
user: System: [2026-04-14 00:53:11 UTC] Exec completed (oceanic-, code 0) :: Skills Status Check Total: 50 ✓ Eligible: 12 ⏸ Disabled: 0 🚫 Blocked by allowlist: 0 ✗ Missing requirements: 38 Ready to use: 🐦 bird
System: [2026-04-14 00:56:15 UTC] Exec completed (faint-ha, code 0) :: :internal/errors:537:14) at ChildProcess.exithandler (node:child_process:417:12) at ChildProcess.emit (node:events:519:28) at maybeClose (node:internal/child_process:1101:16) at ChildProcess._handle.onexit (node:internal/child_process:304:5) { code: 1, killed: true, signal: null, cmd: '/home/ubuntu/.npm-global/bin/openclaw skills check --json', stdout: '', stderr: '' }
System: [2026-04-14 00:56:36 UTC] Exec completed (briny-fj, code 0) :: al/errors:537:14) at ChildProcess.exithandler (node:child_process:417:12) at ChildProcess.emit (node:events:519:28) at maybeClose (node:internal/child_process:1101:16) at ChildProcess._handle.onexit (node:internal/child_process:304:5) { code: 1, killed: true, signal: null, cmd: '/home/ubuntu/.npm-global/bin/openclaw skills check --json', stdout: '', stderr: '' } EXIT:1
System: [2026-04-14 00:58:52 UTC] Exec completed (quick-ce, code 0) :: "skills":{"installed":[{"source":"installed","id":"weather","skillMdPath":"/home/ubuntu/.npm-global/lib/node_modules/openclaw/skills/weather/SKILL.md","relPath":"weather/SKILL.md","mtime":"2026-02-10T13:43:30.397Z"},{"source":"installed","id":"wacli","skillMdPath":"/home/ubuntu/.npm-global/lib/node_modules/openclaw/skills/wacli/SKILL.md","relPath":"wacli/SKILL.md","mtime":"2026-02-10T13:43:30.396
System: [2026-04-14 00:58:53 UTC] Exec completed (ember-da, code 0) :: {"skills":{"installed":[{"source":"installed","id":"weather","skillMdPath":"/home/ubuntu/.npm-global/lib/node_modules/openclaw/skills/weather/SKILL.md","relPath":"weather/SKILL.md","mtime":"2026-02-10T13:43:30.397Z"},{"source":"installed","id":"wacli","skillMdPath":"/home/ubuntu/.npm-global/lib/node
System: [2026-04-14 01:00:16 UTC] Cron: Synced dashboard activity on main and updated data files.
- Ran
npm run sync:activity→ added 1 event (total 1116) - Detected changes in:
data/activity.jsondata/activity-state.json
- Committed + pushed to
main:- Commit:
df4327b—chore: sync activitySystem: [2026-04-14 01:15:14 UTC] Cron: ok System: [2026-04-14 01:30:08 UTC] Cron: No changes detected afternpm run sync:activity(added 0 events; total 1116).
- Commit:
Repo is clean (git status empty), so I did not commit or push.
now getting Couldn't run openclaw skills check: Command failed: /home/ubuntu/.npm-global/bin/openclaw skills check --json and seeing all skills not just the eligible ones? are you sure you implemented the right way? also it took forever to run. tell me what your plan is, don't do anything yet [message_id: aeedff56-efa6-4f3f-b3db-95d0ea20d93c] assistant: You’re seeing the “right” behavior given the way it’s currently written, but it’s not the behavior you want.
What’s happening (and why it feels wrong)
- Why it shows all skills
- The UI’s “Show only eligible” filter only works if we successfully get an
eligiblelist fromopenclaw skills check --json. - When the check errors,
eligibleSetbecomesnull, and the code intentionally falls back to “show everything we can list from disk” (installed + workspace skills). That’s why you suddenly see all skills.
- Why the error is now
Command failed: ... openclaw skills check --json
- In the dashboard, we run the CLI via
execFilewith a 15s timeout. - On your host,
openclaw skills check --jsoncan sometimes take longer than that (especially if it’s doing a bunch of requirement probes, or if it gets called multiple times concurrently). - When it exceeds that timeout, Node kills it and you get that generic “Command failed” error (often with empty stdout/stderr).
- Why it “took forever”
- Two contributors:
- If the page/route is hit multiple times quickly (prefetch, refresh, multiple components), you can get concurrent spawns of
openclaw skills check, which makes everything slower. - Even one run may be slow enough to trip the 15s limit occasionally.
- If the page/route is hit multiple times quickly (prefetch, refresh, multiple components), you can get concurrent spawns of
My plan (no changes yet)
Goal: make Skills page load fast and deterministic, and never “flip” to showing everything just because the eligibility check timed out.
-
Stop doing the expensive check inline on page load
- Keep listing skill files from disk (fast).
- Treat “eligibility check” as a separate, cached piece of data.
-
Introduce a “last known good” eligibility result
- Store the last successful
openclaw skills check --jsonoutput (e.g., JSON indata/or similar). - On error/timeout, keep using the last known good eligible list so the UI still filters correctly.
- Show a warning banner like “Eligibility check stale (last updated X mins ago)” instead of dumping all skills.
- Store the last successful
-
Debounce / single-flight the CLI
- Ensure only one
openclaw skills checkruns at a time (others await the same promise), so a burst of requests doesn’t spawn multiple processes.
- Ensure only one
-
Fix the timeout semantics
- Raise the timeout (e.g. 60s) only for a manual refresh action, not every page load.
- For automatic refresh, keep a shorter budget and fall back to cached results.
-
UI change
- When “Show only eligible” is enabled and the check is unavailable, don’t silently show all; either:
- keep filtering using cached eligible list, or
- show “Eligibility currently unavailable” and keep the list empty (your preference).
- When “Show only eligible” is enabled and the check is unavailable, don’t silently show all; either:
Before I touch anything: which behavior do you prefer when the eligibility check can’t run?
- A) Keep showing the last-known eligible list (stale-but-correct filter), with a “stale” warning
- B) Show an empty list when “only eligible” is on (strict), with an error banner and a “Retry” button
- C) Current fallback (show all) but with clearer messaging (I think this is the worst UX, but offering it)