Skip to content
Scalpels home

Scalpels is officially launching on October 31, 2026. Special early adopter pricing is available now.

← All documentation

Documentation

Capstan

Troubleshooting

Updated

Most Capstan problems are a setting that is missing or a step that was skipped, and many of them fail quietly while the deployment stays green. Start with the symptom.

The Postmaster link is missing from the sidebar

CAPSTAN_FEATURE_POSTMASTER is not true in the running environment. Set it and redeploy; the setting is read when the app boots. While it is off, /postmaster and the poll API return 404.

Artifact links return 404

Work down this list:

  1. The environment has no connected custom domain, or it was not redeployed after the domain connected. Capstan refuses to serve artifacts while the app and render origins are the same.
  2. The artifact has passed its expires_at, or the id is wrong.
  3. The request went to the wrong hostname. The viewer page is served only from the custom app domain and artifact content only from the environment's laravel.cloud address; each refuses the other's requests.

The artifact page opens but the frame is empty or refused

  • A signed_url link without an expires_at is valid for one hour after it was issued. After that it is refused; publish again, or set expires_at for a longer-lived link.
  • An org_auth link only opens for someone signed in to this Capstan.
  • The frame's own content address is valid for at most five minutes. Share the viewer link, never the frame's address.
  • The app's own URL is wrong. Only the app's own origin may frame artifact content, so if the environment's APP_URL does not match the hostname people use, the browser blocks the frame.

Artifact HTML loads but looks broken

The content policy blocks every network request by default: external scripts, stylesheets, fonts, images and fetch calls all fail. Make the HTML self-contained, using inline scripts, inline styles and data: images. If your organisation decides to trust a specific source, add it to the matching CAPSTAN_ARTIFACT_CSP_* allowlist; see Configuration.

If the HTML arrives rewritten or with extra bytes, a CDN or proxy in front of the render hostname is editing it. Capstan sends Cache-Control: no-transform, which Cloudflare honours; turn off HTML rewriting on any other proxy for that hostname.

A token returns 401

  • If you created the token on the personal credentials page, /bfc/ui/credentials/personal, that is expected in the current release: those tokens are rejected by both APIs. Use the device flow in API tokens.
  • Check that X-Capstan-Actor-ID is the id of the person the token was issued to. Capstan rejects a mismatch before doing anything else.
  • Check the token's purpose. An artifact token does not work on the poll endpoint, and a poll token does not work on the artifact endpoint.

Requests return 429 with no error code

You have made more than 60 API requests in a minute across both endpoints. The limit is per person, so every agent and tool using your tokens shares it. Wait for the number of seconds in Retry-After.

Postmaster messages are never delivered

The signing key has not been provisioned. Capstan signs every message as it hands it over and refuses to deliver an unsigned one. Run php artisan bfc:signing-root:provision --local once inside the environment; see Postmaster.

The app will not boot with Postmaster on

The error says Postmaster requires app.timezone to be UTC. Something in your fork changed the application timezone. Put 'UTC' back in config/app.php; message signatures are computed over UTC timestamps, and any other timezone breaks every one of them.

An agent shows red or pending on the map

  1. Is it polling? An agent that has never polled, or has not polled for five minutes, is red whatever else is true. On the agent machine, check crontab -l, then run the poll script under ~/.config/capstan/<server-id>/ by hand and read the error. A bad token or an unreachable host fails silently under cron.
  2. Has it answered a challenge yet? An agent that polls but has not answered its first liveness challenge is pending, not red. That is normal for a new agent; it turns green after its first correct answer.
  3. Did a challenge fail? A wrong answer turns the agent red even while it polls happily. Capstan logs a warning each time an agent turns red.
  4. Only then, the scheduler. The sweep that fails overdue challenges runs every minute on the scheduler Scalpels provisions. If nothing ever moves out of pending, check that the environment's scheduler is running.

An agent receives nothing

The installed poller advertises no inboxes until you add one to ~/.config/capstan/<server-id>/inboxes.json. If that file names an inbox and polls are rejected with 409 inbox_claimed, another person already owns that inbox name; choose a different one.

An invitation never arrives

The members page lists pending invitations but does not show their links, so the invited person depends on the email. Delivery depends on the mail transport the deployment is configured with. If it writes mail to the log instead of sending it, find the invitation link in the application log, which contains /bfc/invitations/, and send it to the person yourself.