heygen-com/hyperframes · error · FigmaClientError

HTTP_ERROR

HTTP_ERROR

Error message

figma request failed: HTTP ${res.status} ${path}

What it means

The catch-all FigmaClientError (code HTTP_ERROR) thrown by throwForStatus for any non-ok response that is not 401, 403, or 429. It surfaces the raw status code and the request path so the developer can diagnose endpoints figma's typed mapping does not special-case — typically 404 (wrong fileKey/node path), 500/502/503 (figma outage), or 400 (malformed request the client assembled incorrectly).

Source

Thrown at packages/core/src/figma/client.ts:287

  /** Throw the typed error for a non-ok response (no-op when res.ok). */
  async function throwForStatus(res: Response, path: string, opts: GetOptions): Promise<void> {
    if (res.ok) return;
    if (res.status === 401)
      throw new FigmaClientError(
        "BAD_TOKEN",
        "figma rejected the token (401) — it is expired or revoked. Re-mint at figma.com/settings → Security, then update FIGMA_TOKEN.",
        401,
        opts.endpoint,
      );
    if (res.status === 403) throw forbiddenError(await readFigmaErrorMessage(res), opts);
    if (res.status === 429)
      throw new FigmaClientError(
        "RATE_LIMITED",
        `figma rate limit hit (429) and still limited after ${maxRetries} retries — wait a minute and re-run, or import fewer nodes per call.`,
        429,
        opts.endpoint,
      );
    throw new FigmaClientError(
      "HTTP_ERROR",
      `figma request failed: HTTP ${res.status} ${path}`,
      res.status,
      opts.endpoint,
    );
  }

  async function get(path: string, opts: GetOptions): Promise<unknown> {
    // Retry 429 with backoff before surfacing RATE_LIMITED — figma's limit is
    // per-minute, so a couple of imports in quick succession hit it and a
    // short wait clears it. Honor Retry-After when present, else exponential.
    let res: Response;
    for (let attempt = 0; ; attempt += 1) {
      res = await doFetch(`${base}${path}`, { headers: { "X-Figma-Token": token } });
      if (res.status !== 429 || attempt >= maxRetries) break;
      const wait = retryAfterMs(res) ?? 1000 * 2 ** attempt;
      await sleep(wait);
    }

View on GitHub (pinned to c2996c8626)

Solutions

  1. Read the status in the error message: 404 -> verify fileKey/nodeId exist and are shared with the token's account; 5xx -> retry after a short wait, likely a figma incident.
  2. Double-check the fileKey has no leading/trailing whitespace or URL fragments.
  3. If using a custom baseUrl (e.g. a proxy), confirm it forwards figma responses unchanged.
  4. For 400s, inspect the exact path in the message and compare against figma's REST docs.
Defensive patterns

Strategy: try-catch

Type guard

import { FigmaClientError } from '.../figma/client';
export function isHttpError(err: unknown): err is FigmaClientError {
  return err instanceof FigmaClientError && err.code === 'HTTP_ERROR';
}

Try / catch

try {
  await client.fileVersion(fileKey);
} catch (err) {
  if (isHttpError(err)) {
    if (err.status === 404) console.error('file not found — check the fileKey');
    else if (err.status && err.status >= 500) { /* transient, retry later */ }
    else throw err;
  } else throw err;
}

Prevention

When it happens

Trigger: A 404 from /v1/files/<wrong-key>/nodes because the fileKey was mistyped or the file was deleted; a 500/502/503 during a figma-side incident; a 400 from a malformed query string the client built; a 405 from hitting the wrong HTTP method on a misconfigured baseUrl.

Common situations: Typo in the fileKey (404); pointing baseUrl at a proxy that returns non-figma status codes; figma API maintenance window (5xx); the node was deleted between a parseFigmaRef call and the nodeTree fetch.

Related errors


AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12). Data as JSON: /api/errors/df003e1085ff4450. Report an issue: GitHub.