{"record":{"id":"cf86f98914806640","repo":"heygen-com/hyperframes","slug":"all-refs-in-one-import-must-share-a-filekey-batch","errorCode":null,"errorMessage":"all refs in one import must share a fileKey (batch is per-file) — got ${fileKey} and ${mixed.fileKey}; run separate commands per file","messagePattern":"all refs in one import must share a fileKey \\(batch is per-file\\) — got (.+?) and (.+?); run separate commands per file","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/figma/asset.ts","lineNumber":185,"sourceCode":"}\n\n/**\n * Import many nodes of ONE figma file. Cache-checks each, renders the misses\n * in a SINGLE /v1/images batch call (figma's documented rate-limit\n * workaround — N nodes, one REST request), freezes each, and regenerates\n * index.md once. Results come back in input order.\n */\nexport async function runAssetImportMany(\n  refInputs: string[],\n  opts: AssetImportOptions,\n  deps: AssetImportDeps,\n): Promise<AssetImportResult[]> {\n  if (refInputs.length === 0) return [];\n  const refs = refInputs.map(requireNodeRef);\n  const fileKey = refs[0]!.fileKey;\n  const mixed = refs.find((r) => r.fileKey !== fileKey);\n  if (mixed)\n    throw new Error(\n      `all refs in one import must share a fileKey (batch is per-file) — got ${fileKey} and ${mixed.fileKey}; run separate commands per file`,\n    );\n\n  const { version } = await deps.client.fileVersion(fileKey);\n  const description = normalizeMeta(opts.description);\n  const entity = normalizeMeta(opts.entity);\n\n  // Resolve cache hits first; batch-render only the misses.\n  const slots: (AssetImportResult | null)[] = refs.map((r) =>\n    reuseExisting(fileKey, r.nodeId, opts, version, deps, description, entity),\n  );\n  const missIndexes = slots.flatMap((s, i) => (s === null ? [i] : []));\n  try {\n    if (missIndexes.length > 0) {\n      const missNodeIds = missIndexes.map((i) => refs[i]!.nodeId);\n      const rendered = await deps.client.renderNodes(fileKey, missNodeIds, opts);\n      const byNode = new Map(rendered.map((r) => [r.nodeId, r] as const));\n      for (const i of missIndexes) {","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/commands/figma/asset.ts#L167-L203","documentation":"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).","triggerScenarios":"`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.","commonSituations":"Selecting frames across multiple figma files and pasting all refs into one command; combining a library file ref with a consuming-file ref.","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"],"exampleFix":"// before: two files in one command (rejected)\nhyperframes figma asset AAA:1:2 BBB:3:4\n// after: one command per file\nhyperframes figma asset AAA:1:2\nhyperframes figma asset BBB:3:4","handlingStrategy":"validation","validationCode":"import { parseFigmaRef } from '@hyperframes/core/figma';\nconst fileKeys = new Set(refs.map(r => parseFigmaRef(r).fileKey));\nif (fileKeys.size > 1) {\n  throw new Error(`batch must share one fileKey; got ${[...fileKeys].join(', ')}`);\n}","typeGuard":"function refsShareFileKey(refInputs: string[]): boolean {\n  const keys = new Set(refInputs.map(r => parseFigmaRef(r).fileKey));\n  return keys.size === 1;\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["figma","asset","batch","validation","file-key"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}