Skip to content

Troubleshooting

Common issues and their fixes.

You see an error like:

schema file already exists at /path/to/.appctl/schema.json (pass --force to replace…)

Wrong directory: appctl picks the first .appctl directory found walking up from your shell’s current path. If a parent folder (for example a repo or ~/ tree) already has a synced schema.json, you get this error even when the current subfolder has no local .appctl. Fix: run sync with an explicit app dir, e.g. appctl sync --app-dir /absolute/path/to/this-api/.appctl --openapi … (or mkdir -p .appctl in that project, then appctl sync --app-dir .appctl …).

Why --force: without it, the CLI will not replace an existing schema.json when you do mean to overwrite. Add --force when re-syncing the same app from the same source.

Fix: pass --force on the same sync line you use for your source:

Terminal window
appctl sync --openapi ... --force

For watch mode, include --force in the one long command, because the second and later re-syncs (when the OpenAPI document changes) are overwrites. See the sync reference on when to use --force.

appctl doctor
list_parcels GET /parcels/ 404 not_found

The sync wrote paths as /parcels/ but your Django app mounts the API under /api/. Include the prefix in --base-url:

Terminal window
appctl sync --django . --base-url http://127.0.0.1:8001/api --force

appctl doctor says “invalid port number”

Section titled “appctl doctor says “invalid port number””

You are on a pre-0.2.0 build. Upgrade. The fix is in doctor.rs: non-root paths now get a slash between base URL and path.

Supabase sync “document missing paths object”

Section titled “Supabase sync “document missing paths object””

Your PostgREST serves the OpenAPI document at / (bare PostgREST) but older builds only probed /rest/v1 (hosted Supabase layout). Upgrade to 0.2.0 or newer. The sync now probes both layouts automatically.

/api/v1/post instead of /api/v1/posts. Fixed in 0.2.0. Upgrade and re-sync with --force.

error: no provider named "claude"

Either the provider is not in .appctl/config.toml, or the default in config.toml points at a name that does not exist. Inspect:

Terminal window
appctl config show

The api_key_ref in your config does not match any keychain entry or environment variable. Store the key:

Terminal window
appctl config set-secret ANTHROPIC_API_KEY --value "$ANTHROPIC_API_KEY"

Or set the env var for the current session:

Terminal window
export ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY"

You started serve with --token but the client is not sending it. Send one of:

  • Authorization: Bearer <TOKEN>
  • X-Appctl-Token: <TOKEN>
  • ?token=<TOKEN> (WebSocket only)
Synced Url: 0 resources, 0 tools written to .appctl

The login worked but the post-login page had no discoverable structure (no forms, no tables, no action links). This source only finds surface the crawler can understand. For SPAs or custom UIs, sync the backing API with --openapi instead.

appctl sync --mcp expects a URL. If your MCP server is stdio-only, wrap it with an HTTP or WebSocket bridge. The examples/demos/mcp-stdio/ example shows the protocol, but it is not a direct target for sync --mcp.

The db-postgres and supabase demos need a running Docker daemon. Start Docker Desktop (or systemctl start docker on Linux) before docker compose up -d.

error: failed to unlock keychain

The keychain needs secret-service running (GNOME Keyring or KWallet). On headless servers, use environment variables instead:

Terminal window
export ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY"
  • Run with --log-level debug for verbose logs.
  • Check .appctl/history.db for the last tool call’s arguments and status.
  • File an issue with the commands, the schema snippet, and the error: github.com/Esubaalew/appctl/issues.