heygen-com/hyperframes · error · Error

figma ref ${ref.fileKey} has no nodeId

Error message

figma ref ${ref.fileKey} has no nodeId

What it means

Thrown by the internal requireNodeId helper when a FigmaRef passed to renderNode or nodeTree has no nodeId. Those two endpoints (/v1/images and /v1/files/:key/nodes) operate on a specific node, unlike file-level calls (imageFills, variables, styles, fileVersion) which only need the fileKey. The library treats a missing nodeId as a programmer error rather than silently fetching the whole file.

Source

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

  try {
    text = await res.text();
  } catch {
    return null;
  }
  try {
    const body: unknown = JSON.parse(text);
    if (isRecord(body)) {
      if (typeof body.err === "string") return body.err;
      if (typeof body.message === "string") return body.message;
    }
  } catch {
    // non-JSON body — fall through
  }
  return text.trim() === "" ? null : text.trim();
}

function requireNodeId(ref: FigmaRef): string {
  if (!ref.nodeId) throw new Error(`figma ref ${ref.fileKey} has no nodeId`);
  return ref.nodeId;
}

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === "object" && value !== null;
}

function optionalString(value: unknown): string | undefined {
  return typeof value === "string" ? value : undefined;
}

function toVariablePayload(payload: unknown): FigmaVariablePayload | null {
  if (!isRecord(payload) || typeof payload.name !== "string") return null;
  return {
    name: payload.name,
    key: optionalString(payload.key),
    resolvedType: optionalString(payload.resolvedType),
    valuesByMode: isRecord(payload.valuesByMode) ? payload.valuesByMode : undefined,

View on GitHub (pinned to c2996c8626)

Solutions

  1. Ensure the figma URL or ref string includes a node id — in the figma UI, right-click a frame → 'Copy link' (the URL then carries ?node-id=...).
  2. If building FigmaRef programmatically, always set nodeId: { fileKey, nodeId: '12:34' }.
  3. Switch to a file-level call (imageFills/styles/variables) if you actually want whole-file data and don't have a node.

Example fix

// before — no nodeId, renderNode cannot target a node
await client.renderNode({ fileKey: 'aBcDeF1234' }, { format: 'png' });

// after — nodeId present (colon-form, as figma uses)
await client.renderNode(
  { fileKey: 'aBcDeF1234', nodeId: '12:34' },
  { format: 'png' },
);
Defensive patterns

Strategy: type-guard

Type guard

import type { FigmaRef } from '.../figma/types';
export function refHasNodeId(ref: FigmaRef): ref is FigmaRef & { nodeId: string } {
  return typeof ref.nodeId === 'string' && ref.nodeId.length > 0;
}
// usage
if (!refHasNodeId(ref)) throw new Error(`ref for ${ref.fileKey} needs a nodeId`);

Prevention

When it happens

Trigger: Calling client.renderNode({ fileKey: 'abc123' }) with no nodeId; calling client.nodeTree({ fileKey: 'abc123' }); parseFigmaRef returning only a fileKey because the input URL had no ?node-id= parameter and no ':node' suffix, then passing that ref to renderNode/nodeTree.

Common situations: User pastes a figma file URL without selecting a frame first (the URL lacks the node-id query param); a CLI flag accepts a bare fileKey but the command targets a node-rendering flow; refactoring that drops the nodeId field from a FigmaRef object literal.

Related errors


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