different-ai/openwork · error · DenApiError

invalid_mcp_token_payload

invalid_mcp_token_payload

Error message

MCP token response was missing required values.

What it means

mintMcpToken POSTs to /v1/mcp/token requesting mcp:read and mcp:write scopes, then parses the payload with parseDenMcpToken. If the response is missing required token values, a 500 DenApiError with code "invalid_mcp_token_payload" is thrown so callers never receive a partially-formed MCP token.

Source

Thrown at apps/app/src/app/lib/den.ts:3100

      });
      // 404 means the memory is already gone (or not owned) — idempotent from the caller's view.
      if (!result.ok && result.status !== 404) {
        const payload = result.json;
        const code = isRecord(payload) && typeof payload.error === "string" ? payload.error : "request_failed";
        throw new DenApiError(result.status, code, getErrorMessage(payload, `Delete failed with ${result.status}.`));
      }
    },

    async mintMcpToken(orgId: string): Promise<DenMcpToken> {
      const payload = await requestJson<unknown>(baseUrls, "/v1/mcp/token", {
        method: "POST",
        token,
        organizationId: orgId,
        body: { scopes: ["mcp:read", "mcp:write"] },
      });
      const minted = parseDenMcpToken(payload);
      if (!minted) {
        throw new DenApiError(500, "invalid_mcp_token_payload", "MCP token response was missing required values.");
      }
      return minted;
    },

    async getWorkerTokens(workerId: string, orgId: string): Promise<DenWorkerTokens> {
      const payload = await requestJson<unknown>(baseUrls, `/v1/workers/${encodeURIComponent(workerId)}/tokens`, {
        method: "POST",
        token,
        organizationId: orgId,
        body: {},
      });
      const tokens = getWorkerTokens(payload);
      if (!tokens) {
        throw new DenApiError(500, "invalid_worker_token_payload", "Worker token response was missing token values.");
      }
      return tokens;
    },

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Verify the Den server version supports MCP token minting with the expected response shape
  2. Log the raw payload to identify the missing field
  3. Re-authenticate and retry if the failure could be session-related
  4. Fix baseUrl/proxy configuration so the real Den server responds

Example fix

// before
const token = await client.mintMcpToken(orgId);
connectMcp(token);
// after
try { connectMcp(await client.mintMcpToken(orgId)); }
catch (err) {
  if (err instanceof DenApiError && err.code === "invalid_mcp_token_payload") throw new Error("MCP token unavailable on this Den server");
  throw err;
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!orgId) throw new Error("An organization id is required to mint an MCP token");

Type guard

const isDenMcpToken = (t: unknown): t is DenMcpToken =>
  typeof t === "object" && t !== null && "token" in t && typeof (t as { token: unknown }).token === "string" && (t as { token: string }).token.length > 0;

Try / catch

try {
  mcpToken = await client.mintMcpToken(orgId);
} catch (err) {
  if (err instanceof DenApiError && err.code === "invalid_mcp_token_payload") {
    throw new Error("This Den server cannot mint MCP tokens; upgrade the server");
  } else throw err;
}

Prevention

When it happens

Trigger: The mint endpoint returns 2xx but the body lacks the expected token fields — server schema drift, wrong server, or a proxy altering the response.

Common situations: Self-hosted Den version without full MCP token support, server-side minting failure swallowed into a 2xx, or misconfigured baseUrl.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/baa0cc4b282a9781. Report an issue: GitHub.