Troubleshooting
skael setup can’t connect
Section titled “skael setup can’t connect”What you see:
✗ Cannot connect to http://localhost:9
http GET /api/health: Get "http://localhost:9/api/health": dial tcp [::1]:9: connect: connection refused
Try: curl http://localhost:9/api/healthWhy: The server isn’t reachable — wrong URL, wrong port, or the process isn’t running.
Fix:
- Confirm the server is up:
curl http://your-host:8080/api/health— you should get{"status":"ok"}. - Check
LISTEN_ADDRin.env(default:8080). If you changed it, use the same port inskael setup. - Make sure the container or process is started (
docker compose up -dorsystemctl start skael).
401 / invalid API key
Section titled “401 / invalid API key”What you see (from skael list or any CLI command):
✗ API error 401: {"error":"unauthorized"}Why: The API key in ~/.skael/config.json is revoked, expired, or was never created for this server.
Fix:
- Log in to the dashboard → Settings → API keys → create a new key.
- Re-run setup with the new key:
skael setup <url> <new-key>. - If you rotated the key manually, you can also edit
~/.skael/config.jsondirectly — the field isapi_key.
Sync runs but skills don’t appear in the agent
Section titled “Sync runs but skills don’t appear in the agent”What you see: skael sync completes without errors but the skill files aren’t where you expect them.
Why: Scope mismatch. Sync places skills under either the project root (.claude/skills/, .cursor/rules/, etc. relative to the nearest .git) or the user home (~/.claude/skills/, etc.). The default is project. If you ran sync from a directory that isn’t inside a git repo, the project root falls back to the current working directory.
Fix:
Run skael doctor to see the resolved path for each detected agent:
✓ claude-code: 3 skill(s) in ~/.claude/skills, hook installedAdd --json for scripting:
skael doctor --json | jq '.checks[] | {name, detail}'To change scope permanently, re-run setup with --scope user:
skael setup <url> <key> --scope userOr pass --scope per-sync:
skael sync --scope userproject— skills land in<git-root>/.claude/skills(or agent equivalent). Shared when you commit.claude/.user— skills land in~/.claude/skills. Available in all projects.
checksum mismatch during sync
Section titled “checksum mismatch during sync”What you see (from skael sync):
! checksum mismatch for my-skill (expected a1b2c3d4e5f60718, got 9f8e7d6c5b4a3210)Source: cli/sync.go — the warning fires when the SHA-256 of the downloaded archive doesn’t match the checksum recorded in the manifest.
Why: The archive file on the server doesn’t match the checksum stored in the database. This happens after a partial restore — the database was restored to a newer state than the archive store, or vice versa.
Fix:
- Re-publish the affected skill:
skael publish <skill-dir>. This uploads a fresh archive and updates the manifest checksum. - If you’re restoring from backup, make sure both the database dump and the archive store (
STORAGE_PATH) are from the same snapshot. See the backup and restore guide.
Publish rejected: critical security findings
Section titled “Publish rejected: critical security findings”What you see (from skael publish):
/tmp/my-skill/SKILL.md:9 critical AWS access key ID detected /tmp/my-skill/SKILL.md:8 critical AWS access key ID detected
2 critical · 0 high · 0 medium · 0 info ✗ critical security findings block publish
Try: skael publish --forceWhy: The scanner found a secret (AWS key, token, private key, etc.) in the skill files. Both critical and warn (high severity) block publishing to protect your team.
Fix:
- Run
skael scan <dir>locally to see every finding with file and line numbers. Exit codes:0= clean,1= warn/high,2= critical. - Remove or replace the secret. Use environment variables or
~/.skael/config.jsonpatterns instead of hard-coded values. - Re-publish. If the finding is a deliberate example (documentation, test fixture), use
skael publish --force— but only when you’re certain the value is not a live credential.
Database connection refused at startup
Section titled “Database connection refused at startup”What you see in the server log:
{"level":"fatal","error":"ping database: failed to connect to `user=skael database=skael`:\n\t[::1]:5432 (localhost): dial error: dial tcp [::1]:5432: connect: connection refused\n\t127.0.0.1:5432 (localhost): dial error: dial tcp 127.0.0.1:5432: connect: connection refused","time":"...","message":"database connection error"}Source: cmd/server/main.go — log.Fatal().Err(err).Msg("database connection error").
Why: The server can’t reach Postgres. The most common causes are: Postgres hasn’t started yet, DATABASE_URL points to the wrong host/port, or there’s a firewall between the two.
Fix:
- Confirm Postgres is running:
pg_isready -h localhost -p 5432ordocker ps. - Check
DATABASE_URLin.env— host, port, user, password, and database name must all match. - If using Docker Compose, add a
depends_onhealthcheck so skael waits for Postgres to be ready before starting:See the production deployment guide for a full example.depends_on:db:condition: service_healthy
Dashboard login loop
Section titled “Dashboard login loop”What you see: You log in, get redirected back to the login page immediately — no error shown.
Why: COOKIE_SECURE=true is set but the server is serving plain HTTP (no TLS proxy in front). The browser refuses to store a Secure cookie over HTTP, so the session is never saved. Every request after login appears unauthenticated.
Source: internal/server/server.go — sessionManager.Cookie.Secure = os.Getenv("COOKIE_SECURE") == "true".
Fix:
- In production: put a TLS-terminating reverse proxy (Caddy, nginx) in front of skael before enabling
COOKIE_SECURE=true. See the production deployment guide. - In development: unset
COOKIE_SECURE(or set it tofalse) in.env. The default isfalse, so this only happens if you explicitly set it.
Hooks installed but no activations
Section titled “Hooks installed but no activations”What you see: skael hook status shows hooks installed, but the Activations tab in the dashboard stays empty.
Why: The hook script reads credentials from ~/.skael/config.json at runtime — credentials are never embedded in the agent config file. If that config file is missing, moved, or has an empty api_key field, the hook exits silently (exit 0) without posting any events.
Source: cli/hooks/script.go — the hook script checks [ ! -f "$CONFIG_FILE" ] and exits if the file is absent.
Fix:
- Check hook installation status:
Terminal window skael hook status - Confirm
~/.skael/config.jsonexists and has a validendpointandapi_key:Terminal window cat ~/.skael/config.json - If the config is missing or stale, re-run setup to restore it:
Terminal window skael setup <url> <api-key> - Re-install hooks explicitly:
Terminal window skael hook install
After re-installing, trigger a skill invocation and check the Activations tab — events appear within a few seconds.