{"record":{"id":"4d321cd4fef42796","repo":"heygen-com/hyperframes","slug":"bad-token","errorCode":"BAD_TOKEN","errorMessage":"figma rejected the token (401) — it is expired or revoked. Re-mint at figma.com/settings → Security, then update FIGMA_TOKEN.","messagePattern":"figma rejected the token \\(401\\) — it is expired or revoked\\. Re-mint at figma\\.com/settings → Security, then update FIGMA_TOKEN\\.","errorType":"error_code","errorClass":"FigmaClientError","httpStatus":401,"severity":"error","filePath":"packages/core/src/figma/client.ts","lineNumber":273,"sourceCode":"        403,\n        opts.endpoint,\n      );\n    const scopeLine = opts.scopeHint\n      ? `This endpoint needs the \"${opts.scopeHint}\" scope — add it at figma.com/settings → Security → Personal access tokens.`\n      : \"The token is missing a read scope, or your account can't view this file. Check File content: Read-only + File metadata: Read-only at figma.com/settings → Security.\";\n    return new FigmaClientError(\n      \"FORBIDDEN\",\n      `figma denied access (403). ${scopeLine} Also confirm the file is visible to your account.`,\n      403,\n      opts.endpoint,\n    );\n  }\n\n  /** Throw the typed error for a non-ok response (no-op when res.ok). */\n  async function throwForStatus(res: Response, path: string, opts: GetOptions): Promise<void> {\n    if (res.ok) return;\n    if (res.status === 401)\n      throw new FigmaClientError(\n        \"BAD_TOKEN\",\n        \"figma rejected the token (401) — it is expired or revoked. Re-mint at figma.com/settings → Security, then update FIGMA_TOKEN.\",\n        401,\n        opts.endpoint,\n      );\n    if (res.status === 403) throw forbiddenError(await readFigmaErrorMessage(res), opts);\n    if (res.status === 429)\n      throw new FigmaClientError(\n        \"RATE_LIMITED\",\n        `figma rate limit hit (429) and still limited after ${maxRetries} retries — wait a minute and re-run, or import fewer nodes per call.`,\n        429,\n        opts.endpoint,\n      );\n    throw new FigmaClientError(\n      \"HTTP_ERROR\",\n      `figma request failed: HTTP ${res.status} ${path}`,\n      res.status,\n      opts.endpoint,","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/core/src/figma/client.ts#L255-L291","documentation":"Thrown by throwForStatus (code BAD_TOKEN, status 401) when figma's REST API returns HTTP 401 on a GET. A 401 means the X-Figma-Token was syntactically a token but figma no longer accepts it — it has expired or been revoked. The error points the user back to the PAT settings page to re-mint. (Note: figma also returns 403 with body 'Invalid token' for some bad-token cases on file endpoints — those are handled separately by forbiddenError at client.ts:237 and surface the same BAD_TOKEN code.)","triggerScenarios":"Any client call (renderNode, nodeTree, styles, variables, fileVersion, imageFills) after the PAT was deleted or expired in figma; using a token from a different figma account than the one that owns the file (can also 403); a token that was regenerated in the UI but FIGMA_TOKEN in the shell still holds the old value.","commonSituations":"Token expired (figma PATs can have expirations or be revoked); the user regenerated a token and forgot to update the .env/shell; token pasted with trailing whitespace stripped wrongly (less likely since createFigmaClient trims); switching figma accounts mid-project.","solutions":["Open figma.com/settings -> Security -> Personal access tokens and generate a new token.","Update FIGMA_TOKEN in your shell (export FIGMA_TOKEN=...) and in the project .env / CI secret.","Re-run the command that failed — the new token takes effect on the next createFigmaClient call.","If it persists, confirm the token's scopes include File content: Read-only."],"exampleFix":"// before — stale token in env\nexport FIGMA_TOKEN=\"figd_old_revoked_value\"\n\n// after — freshly minted token\nexport FIGMA_TOKEN=\"figd_newly_generated_value\"","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"import { FigmaClientError } from '.../figma/client';\nexport function isBadToken(err: unknown): err is FigmaClientError {\n  return err instanceof FigmaClientError && (err.code === 'BAD_TOKEN');\n}","tryCatchPattern":"try {\n  await client.nodeTree(ref);\n} catch (err) {\n  if (isBadToken(err)) {\n    // prompt the user to re-mint the PAT, update FIGMA_TOKEN, retry once\n  } else throw err;\n}","preventionTips":["Treat figma PATs as rotating credentials — set a calendar reminder before expiry.","When a token is regenerated, update every environment (shell, .env, CI) in lockstep.","Wrap figma calls in a helper that catches BAD_TOKEN and surfaces a re-setup prompt rather than a raw stack trace."],"tags":["figma","auth","http","credentials"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}