heygen-com/hyperframes · error · Error

all refs in one import must share a fileKey (batch is per-fi

Error message

all refs in one import must share a fileKey (batch is per-file) — got ${fileKey} and ${mixed.fileKey}; run separate commands per file

What it means

Thrown by runAssetImportMany() before any network call. The batch path issues a SINGLE /v1/images request scoped to one figma file, so all refs must share refs[0].fileKey. It scans for the first ref whose fileKey differs and names both keys in the message. This is figma's documented rate-limit workaround (N nodes, one request).

Source

Thrown at packages/cli/src/commands/figma/asset.ts:185

}

/**
 * Import many nodes of ONE figma file. Cache-checks each, renders the misses
 * in a SINGLE /v1/images batch call (figma's documented rate-limit
 * workaround — N nodes, one REST request), freezes each, and regenerates
 * index.md once. Results come back in input order.
 */
export async function runAssetImportMany(
  refInputs: string[],
  opts: AssetImportOptions,
  deps: AssetImportDeps,
): Promise<AssetImportResult[]> {
  if (refInputs.length === 0) return [];
  const refs = refInputs.map(requireNodeRef);
  const fileKey = refs[0]!.fileKey;
  const mixed = refs.find((r) => r.fileKey !== fileKey);
  if (mixed)
    throw new Error(
      `all refs in one import must share a fileKey (batch is per-file) — got ${fileKey} and ${mixed.fileKey}; run separate commands per file`,
    );

  const { version } = await deps.client.fileVersion(fileKey);
  const description = normalizeMeta(opts.description);
  const entity = normalizeMeta(opts.entity);

  // Resolve cache hits first; batch-render only the misses.
  const slots: (AssetImportResult | null)[] = refs.map((r) =>
    reuseExisting(fileKey, r.nodeId, opts, version, deps, description, entity),
  );
  const missIndexes = slots.flatMap((s, i) => (s === null ? [i] : []));
  try {
    if (missIndexes.length > 0) {
      const missNodeIds = missIndexes.map((i) => refs[i]!.nodeId);
      const rendered = await deps.client.renderNodes(fileKey, missNodeIds, opts);
      const byNode = new Map(rendered.map((r) => [r.nodeId, r] as const));
      for (const i of missIndexes) {

View on GitHub (pinned to c2996c8626)

Solutions

  1. Run one `figma asset` command per file
  2. Group refs by fileKey first, then issue a batch per group
  3. Verify each ref's fileKey with parseFigmaRef before batching

Example fix

// before: two files in one command (rejected)
hyperframes figma asset AAA:1:2 BBB:3:4
// after: one command per file
hyperframes figma asset AAA:1:2
hyperframes figma asset BBB:3:4
Defensive patterns

Strategy: validation

Validate before calling

import { parseFigmaRef } from '@hyperframes/core/figma';
const fileKeys = new Set(refs.map(r => parseFigmaRef(r).fileKey));
if (fileKeys.size > 1) {
  throw new Error(`batch must share one fileKey; got ${[...fileKeys].join(', ')}`);
}

Type guard

function refsShareFileKey(refInputs: string[]): boolean {
  const keys = new Set(refInputs.map(r => parseFigmaRef(r).fileKey));
  return keys.size === 1;
}

Prevention

When it happens

Trigger: `figma asset AAA:1:2 BBB:3:4` (two different file keys); two figma URLs from different files passed as separate positionals; mixing a fileKey:nodeId token with a URL that resolves to a different fileKey.

Common situations: Selecting frames across multiple figma files and pasting all refs into one command; combining a library file ref with a consuming-file ref.

Related errors


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