Skip to content

Troubleshooting

2DAITeam edited this page Oct 11, 2026 · 3 revisions

Troubleshooting

Tool failures never crash the server — every error comes back to the agent as a one-line, actionable message. This page covers the ones people actually hit, plus the host-setup issues that happen before any tool can run.

The server doesn't appear in my host

Work through these in order:

  1. Node 18+. node --version in the same environment your host runs in. The package declares engines: node >=18 and will not run on older runtimes.

  2. Run it by hand to see the real error — the same command your host runs:

    TWODAI_API_KEY=2dai_sk_... npx -y 2dai-mcp-server

    A healthy server prints [2dai-mcp-server] ready on stdio to stderr and then waits silently. Anything else it prints is your diagnosis.

  3. Stale npx cache. npx -y 2dai-mcp-server@latest forces the current version past a cached older one. If npx behaves strangely, clear its cache (npm cache clean --force) and retry.

  4. Config file validity. A single trailing comma makes some hosts silently ignore the whole mcpServers block. Validate the JSON.

  5. Restart the host. Claude Desktop and most others only read MCP config at startup.

The server starts, then immediately exits

That's a config error, printed to stderr — almost always:

TWODAI_API_KEY is not set. Create a key at https://2dai.io → Dashboard →
Integrations → API keys, then add it to this server's "env" block in your
MCP client config.

Put the key in the server's env block (see Getting Started). The key is read from the environment only — it can't be supplied as a tool argument.

Never let anything print to stdout

On stdio transports, stdout is the JSON-RPC channel. If you wrap the binary in a shell script, a version manager shim, or a launcher that prints anything to stdout (an nvm banner, an echo, a greeting), the very first stray byte corrupts the stream and the host drops the connection with an unhelpful "server disconnected". The server itself writes all diagnostics to stderr — keep it that way: launch npx -y 2dai-mcp-server directly, and if you must wrap it, make the wrapper stdout-silent.

"The API key was rejected" (INVALID_API_KEY)

The key in TWODAI_API_KEY is mistyped, truncated, or was revoked (revocation is instant, and it hits read-only calls like get_account too). Check for copy/paste damage first — the key is the full 2dai_sk_… string, shown once at creation. If in doubt, mint a fresh key at 2dai.io → Dashboard → Integrations → API keys and swap it into the config, then restart the host.

"This API key lacks the scope…" (MISSING_SCOPE)

Scopes are set per key, at mint time, in Dashboard → Integrations → API keys. The error names the missing scope:

  • generate — the key can read but not create. Mint a key with generate (uploads and cancels need it too).
  • manage — organising (move/trash/folders/groups) was blocked.
  • publish — the agent tried to publish/unpublish.
  • finance — the wallet tools. This scope is opt-in and never pre-selected; existing keys don't gain it retroactively, so mint a finance-scoped key if you want wallet reads. See Stats & Wallet.

Keys are create/revoke only — to change scopes, mint a new key, update the config, revoke the old one.

"Out of credit" (INSUFFICIENT_CREDIT)

Generations burn the account's USD credit; when it can't cover the next generation's price the call is refused before any charge, with the shortfall. Top up in the dashboard's Credit section, then just retry. The related "spend cap reached" (KEY_SPEND_LIMIT_REACHED) means this key's own USD ceiling is exhausted while the account may still have credit — raise or remove the cap in Dashboard → Integrations → API keys.

A generation "timed out"

Almost never a real failure. A generate_* call blocks up to its wait budget (45 s by default) and then hands back a queueId — video and high-quality images routinely outlive the budget. Ask the agent to run check_generation with that queueId; the job kept running server-side and the charge stands. Two rules of thumb:

  • Collect, don't re-submit — a re-submitted prompt is a new generation and a new charge. (Accidental rapid duplicates are protected: an identical submit inside the ~30 s idempotency window is refused as IDEMPOTENT_RETRY without charging.)
  • Old queueIds don't expire — settled jobs are archived, never deleted, so check_generation keeps answering.

If you want longer one-shot calls, raise TWODAI_WAIT_BUDGET_MS; if your host's own tool timeout is short, lower it and lean on the ticket flow.

"Too late to cancel" (NOT_PENDING)

cancel_generation only works while the job is still waiting in the queue. Once a worker has it, there is no abort hook — let it finish and collect it with check_generation. The race is benign: either you cancelled in time and were refunded, or you keep the result. A job that fails on its own is refunded automatically.

"No cached $2DAI price quote" (PRICE_UNAVAILABLE)

get_token_price serves the platform's cached quote and never triggers a live refresh. If no cache exists yet you get this message — retry in a few minutes, and never treat it as a zero price.

"Refusing to read/write outside the working directory"

upload_image and download_creation paths are sandboxed to the server's working directory — symlinks included. Either keep files inside the project, or start the server with TWODAI_FILE_ACCESS=any in its env block if you accept agents touching arbitrary paths. See Library & Drive.

"This server runs without filesystem access (hosted mode)"

You are on mcp.2dai.io (or a server started with TWODAI_FILE_ACCESS=none): its disk is not yours. Upload with base64 instead of path; download by calling download_creation without savePath and fetching the downloadUrl it returns, with the same Authorization: Bearer header you send to the server.

Other messages you may see

Message says… It means
"Blocked by content moderation" The prompt or upload tripped moderation beyond the account's NSFW settings — rephrase, or adjust the account policy on 2dai.io
"Your tier does not include this option" A tier-gated option (a video length, an ultra / ultimate preset, Gen8 Preview images below Holder) — the message names the tier that opens it; nothing was charged — see Dashboard → Tiers
KEY_POLICY_CHANNEL The API key's policy stops at the default model channel: imageModel / videoModel: "next" is refused uncharged — submit on the default model or use a key without a channel policy
TOO_MANY_REFS A tool's strict reference cap (generate_image: 3, or 6 with imageModel: "next") — nothing was charged, drop references
"Too many generations already running" The account's parallel-queue cap — wait for one to land or poll with check_generation
"Rate limited" Sustained call pressure — space the calls out a few seconds
Similar-generation refused Raw uploads and wallpaper outputs can't be re-derived by generate_similar, by design — generate them fresh instead
"Permanent delete only works on a trashed creation" Deletion is two-step by design: trash first, then delete
"That image is already in the target folder" Duplicate-upload guard: same pixels, same folder

Still stuck? Check the underlying client's wiki — 2dai-cloud-sdk — for the full error catalogue, or open an issue on the 2dai-mcp-server repo.