Skip to main content

Command Palette

Search for a command to run...

BDK

Fix common agent problems

Start with three checks:

  1. Run bdk validate --dir ..
  2. Confirm the expected agent and connections in bdk info --dir . --json.
  3. Reproduce once, then inspect the serve log or session trace.

Match the visible symptom below.

Serve or the playground will not work

What you seeWhat to do
serve exits before listeningFix the errors from bdk validate --dir ., then start it again.
Playground is blank or says there are no agentsStart bdk serve; built playground assets have no agent data without the server.
Agent-file edits do not appearOpen the URL printed by serve --dev, then press Enter in its TTY to reload after file changes.
Sessions exist but the list is emptyThe list is scoped to the authenticated principal. Use the same identity that created the session; a ?sessionId= deep link does not bypass authorization.
The preferred port is busyUse the next port printed by the CLI, pass --port <number>, or pass --port 0 for any free port.

A model turn fails

What you seeWhat to do
File reads and greps fail repeatedly with NGHTTP2_FRAME_SIZE_ERRORRun the agent under Node 22.13 or newer, never Bun.
The turn immediately reports a missing API keySet CURSOR_API_KEY, CURSOR_API_KEY_FILE, or CURSOR_SERVICE_ACCOUNT_KEY, or run bdk login.
Login succeeds but the model host rejects the keyPoint login and model traffic at the same API host; check CURSOR_API_BASE_URL and CURSOR_BACKEND_URL.
The first turn reports [resource_exhausted]Treat it as a capacity-shaped error. For a GitHub wake, also check the connected GitHub credential and any GitHub 429 rate limit before assuming the model quota is exhausted.

A turn behaves unexpectedly

What you seeWhat to do
Replies quote an ancestor AGENTS.md or unrelated repository rulesInspect local.cwd in /v1/info. Set defineAgent({ local: { cwd } }) or the session workspace explicitly instead of inheriting the parent checkout.
The model lists IDE meta-tools but never calls named MCP toolsSet advertiseTools: true on the local model-visible connection and confirm it under connections in /v1/info.
Server tools, skills, or seed files are absentCheck the discovered project in /v1/info; follow the capability warning from validate.
validate and run pass but CI type-checking failsRun the project type check. Tool results must be JSON-shaped; prefer object literals or type aliases over interface return types.

HTTP returns 401, 403, or 409

What you seeWhat to do
401 outside local developmentSend the configured bearer token, alias token, or channel credential. Default custom routes admit direct loopback only.
403 on a stream or follow-upUse the same authenticated principal that created the session.
A custom channel route fails through a tunnel or LANProtect the shared host with --bearer-token or authored channel auth. Use --allow-anonymous only behind a proxy that authenticates every caller.
409 on a follow-upRefresh the rotating continuationToken and confirm the target is a chat session; task sessions do not accept follow-ups.
409 session_busy from call --sessionWait for the turn, omit --session, or mark a read-only tool with effect: "read" so it can run concurrently.
A custom route fails schema type-checkingAdd the required Zod querySchema for GET, or bodySchema for POST, PUT, and PATCH. See Channels.

A hosted deployment fails or looks stale

What you seeWhat to do
validate or deploy reports architecture "v2" requires a named secretA githubChannel credential or a GitLab or Bitbucket webhookSecret is a literal or a getter. Replace it with the quoted { secretName: "NAME" } and set the value with bdk secrets set <slug> NAME. See Other hosts.
Local changes do not appear after deploydeploy reads a pushed Git ref, not the working tree. Commit and push the intended ref, then deploy it again.
The deployment never becomes runningRun bdk deployment <slug>, then act on the reported build or startup error.
A secret or egress change has no effectConfirm the name with secrets list, verify the hosting block exists on the pushed ref, and follow the CLI or dashboard prompt to redeploy.
Cursor events stopped after redeployEach redeploy replaces the watched repositories. Pass every --cursor-events-repo value again; without the flag, the deployment watches only its GitHub source repository.
run --prod prints a deliveryId but no sessionIdExpected, with or without --dry-run: the session is created when the turn starts. Find it with bdk logs --prod --once --slug <slug>, then follow Verify a hosted turn.
session <sessionId> --prod shows a running run with no logsRuns lag behind events, and a high-effort turn can take several minutes. Rerun the command; a growing event count means the turn is still working.
A dashboard link to a single session doesn't openCheck the session with bdk session <sessionId> --prod --slug <slug>.
chat, call, sessions, cost, or mcp with --prod says the command is not supportedHosted deployments accept --prod only on run, session, logs, and playground. See Verify a hosted turn.
run --prod --session <sessionId> reports the session belongs to another channel--session continues only sessions that run --prod or session --prod started. Reach Slack, SCM, and custom-route sessions through their own channel.
A custom route returns 202 with no bodyExpected on managed hosting. The handler runs after the response, so deliver results from the channel. See Route responses.
External HTTP rejects the alias tokenUpdate the caller with the current token. If the token is lost or exposed, run bdk rotate-token <slug> and replace it everywhere.
deploy, a hosted session, or an eval run says it is not available with Privacy Mode (Legacy)Switch to Privacy Mode, or ask a team admin if your team enforces this setting. A refused session does not store the message. See Privacy Mode.
deploy says persistent deployments are limited to 1 per teamAnother deployment of the team already sets persistent: true. Remove the setting from one agent, or delete that deployment.
A schedule does not fire on the hosted deploymentMake sure the deployment is running and its release has the schedule. Deploy again with @cursor/bdk 0.2.14 or newer.
A request to a custom route gets 429The deployment received more requests than its limit. Wait for the time in Retry-After, then send the request again.

See Deployment for source, credential, and redeployment boundaries.

GitHub deliveries fail

What you seeWhat to do
github forward returns 401 on every delivery after creating the hookClear GITHUB_TOKEN and GH_TOKEN for that command so the forwarder uses the gh CLI login: GITHUB_TOKEN= GH_TOKEN= bdk github forward ....
Hook already existsRun one forwarder for the repository and stop the stale process.
Direct webhook deliveries are rejected outside --devConfigure the same GITHUB_WEBHOOK_SECRET on the signer and server. Cursor event pull needs no public webhook or webhook secret.
You cannot create a forwarderUse bdk github replay <pr-url>; it needs pull access instead of repository administration.

The GitHub guide covers event pull, replay, and direct webhooks.

Slack does not respond

What you seeWhat to do
Logs say channel idle ... missing credentialsRun bdk slack create --dir <agent>, then check the generated prefix with bdk slack doctor. Use slack init --manual only for an app you own.
slack create is waiting for workspace approvalKeep the CLI running, open the Request approval link it prints, and select Retry in the dashboard's Add Slack wizard after an admin approves. See Slack.
The bot ignores ordinary channel postsConfigure engagement.channelPosts, create the app with --channel-posts, and invite it to every allowed channel.

See the Slack guide for app setup and engagement choices.

MCP authorization fails

What you seeWhat to do
must be defineConnection({ url, oauth: true })Add oauth: true to the named URL connection or correct the connection filename passed to mcp oauth.
Local auth works but hosted calls return unauthorizedLocally stored OAuth tokens don't reach a deployment. Use a cursorAccount: true connection and connect the server from Deployed Agents in the dashboard. See Host MCP OAuth.
The model invents mcp_auth instead of calling the serverSet advertiseTools: true for named local tools, or expose a host-side wrapper through ctx.host.mcp.

See Host MCP OAuth for the credential lifecycle.

Schedules or reminders stall

What you seeWhat to do
A schedule or reminder never fires under --devTrigger it through the matching /v1/dev/schedules/<id> or /v1/dev/reminders/<id> route; development mode does not auto-fire.
A reminder is disarmed with handler_lost_on_restartRecreate handler-form reminders after restart, or use a prompt-form reminder.
The same schedule fires on several self-hosted processesEnable schedules on one serving process per project and pass --no-schedules to the others.

A credential was exposed

What you seeWhat to do
A secret value appears in a command, transcript, or shell historyRotate it at the provider, set it again through hidden input or stdin, and test the feature.
An alias token appears outside its secure destinationRun bdk rotate-token <slug>, store the new value outside transcripts, and update every caller.
Someone printed a secret to verify itRotate it. Confirm only the name with bdk secrets list <slug>, then redeploy and exercise the feature.

Read the session trace

Start with actions.requested and action.result. Count calls by tool name, pair every request with its result, and separate host preparation from tools chosen by the model.

turn.failed with turn interrupted usually means a follow-up or stop ended the turn deliberately. Other failures should have an error event near the tool or model boundary that produced them.

Use the trace path printed by bdk run:

bdk trajectory --events <trace-path>

The playground's Open trace control renders the same trajectory. When the agent runs but makes poor decisions, move from diagnosis to a measured hillclimb.