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
- Run one `figma asset` command per file
- Group refs by fileKey first, then issue a batch per group
- 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
- Group refs by fileKey before batching — one command per file
- Validate the shared fileKey in your wrapper before calling runAssetImportMany
- Keep multi-file imports as separate CLI invocations
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
- ref "${refInput}" has no node id — share a link with ?node-i
- unsupported format "${raw}" — use one of ${FORMATS.join(", "
- ${source}: ${errorMessage(error)}
- --batch must be a JSON array of objects, or an object with a
- ${source} contains zero rows.
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/cf86f98914806640.
Report an issue: GitHub.