mastra-ai/mastra · error · PlatformApiError

Failed to create API key — ${await extractError(res)}

Error message

Failed to create API key — ${await extractError(res)}

What it means

mintOrgApiKey POSTs to /v1/auth/tokens with `{ name: keyName }` and org auth headers to mint a new org-scoped API key. Any non-ok response becomes a PlatformApiError with the upstream status and server error text, prefixed with 'Failed to create API key —'.

Source

Thrown at mastracode/mastra-factory/src/platform.ts:109

 * POST /v1/auth/tokens — mint an `sk_` WorkOS org API key.
 * Returns the plaintext secret; the platform never returns it again.
 */
export async function mintOrgApiKey({
  token,
  orgId,
  keyName,
}: {
  token: string;
  orgId: string;
  keyName: string;
}): Promise<string> {
  const res = await platformFetch(`${MASTRA_PLATFORM_API_URL}/v1/auth/tokens`, {
    method: 'POST',
    headers: { ...authHeaders(token, orgId), 'Content-Type': 'application/json' },
    body: JSON.stringify({ name: keyName }),
  });
  if (!res.ok) {
    throw new PlatformApiError(res.status, `Failed to create API key — ${await extractError(res)}`);
  }
  const body = (await res.json()) as CreateTokenResponse;
  return body.secret;
}

/**
 * POST /v1/server/projects/:id/databases — attach a Neon Postgres database.
 * Returns immediately with `status: 'provisioning'`; poll for `ready`.
 *
 * Note: this route requires `requireRole('admin')`. Non-admin org members
 * will get a 403.
 */
export async function attachNeonDatabase({
  token,
  orgId,
  projectId,
  name,
  regionId,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Check the message after the em-dash and address the stated cause (auth, name collision, permissions).
  2. Re-authenticate to refresh an expired token, then rerun create-factory.
  3. Ask an org admin to run the command or mint the key from the dashboard if your role lacks permission.
  4. Retry after backoff if the status is 429 or 5xx.

Example fix

// before
const secret = await mintOrgApiKey({ token, orgId, keyName: 'factory' });
// after
let secret: string;
try {
  secret = await mintOrgApiKey({ token, orgId, keyName: 'factory' });
} catch (e) {
  if (e instanceof PlatformApiError && e.status === 409) {
    secret = await mintOrgApiKey({ token, orgId, keyName: `factory-${Date.now()}` });
  } else throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!keyName || keyName.length > 100) throw new Error('API key name must be 1-100 chars');
// optionally verify uniqueness if the platform lists existing tokens:
const tokens = await listOrgTokens({ token, orgId });
if (tokens.some(t => t.name === keyName)) throw new Error(`Key name '${keyName}' already exists`);

Type guard

function isPlatformApiError(e) { return e instanceof PlatformApiError; }

Try / catch

try {
  secret = await mintOrgApiKey({ token, orgId, keyName });
} catch (err) {
  if (err instanceof PlatformApiError && (err.status === 429 || err.status >= 500)) {
    await sleep(2000); secret = await mintOrgApiKey({ token, orgId, keyName });
  } else throw err;
}

Prevention

When it happens

Trigger: POST /v1/auth/tokens returns 4xx/5xx: 401/403 for expired token or insufficient org permissions, 409/422 for a duplicate or invalid key name, 429 rate limiting, 5xx platform errors.

Common situations: Non-admin user trying to mint org keys; token expired mid-provisioning; key name colliding with an existing token; org hitting key-count limits; transient 502/503 from the platform.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/dfcc0a47dc7db045. Report an issue: GitHub.