{"record":{"id":"c1bf15230fcca5ab","repo":"heygen-com/hyperframes","slug":"ref-refinput-has-no-node-id-share-a-link-wi","errorCode":null,"errorMessage":"ref \"${refInput}\" has no node id — share a link with ?node-id=… or use fileKey:nodeId","messagePattern":"ref \"(.+?)\" has no node id — share a link with \\?node-id=… or use fileKey:nodeId","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/figma/asset.ts","lineNumber":70,"sourceCode":"\n/**\n * Flatten CLI positionals into asset refs. Comma-splits bare\n * `fileKey:nodeId` tokens (so `asset A,B` batches) but leaves URL tokens\n * whole — a figma URL can carry commas in its query (multi-select\n * `node-id=1:2,3:4`), and splitting those would tear the URL apart. To batch\n * URLs, pass them as separate positional args.\n */\nexport function gatherAssetRefs(positionals: string[]): string[] {\n  return positionals\n    .flatMap((r) => (/^https?:/i.test(r.trim()) ? [r] : r.split(\",\")))\n    .map((r) => r.trim())\n    .filter((r) => r.length > 0);\n}\n\nfunction requireNodeRef(refInput: string): { fileKey: string; nodeId: string } {\n  const ref = parseFigmaRef(refInput);\n  if (!ref.nodeId)\n    throw new Error(\n      `ref \"${refInput}\" has no node id — share a link with ?node-id=… or use fileKey:nodeId`,\n    );\n  return { fileKey: ref.fileKey, nodeId: ref.nodeId };\n}\n\n/** Cache hit per spec §5 (fileKey:nodeId:format:scale:version). Check EVERY\n * row for the node — a node can carry several format/scale/version tuples,\n * and the oldest-row shortcut minted duplicates forever. Reuse requires the\n * frozen file to still exist; a deleted file falls through to re-import.\n * Metadata supplied on a re-import upserts rather than being discarded. */\nfunction reuseExisting(\n  fileKey: string,\n  nodeId: string,\n  opts: AssetImportOptions,\n  version: string,\n  deps: AssetImportDeps,\n  description: string | undefined,\n  entity: string | undefined,","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/commands/figma/asset.ts#L52-L88","documentation":"Thrown by requireNodeRef() in figma asset import. It calls parseFigmaRef(refInput); if no nodeId is resolved it refuses. parseFigmaRef yields no nodeId for: a bare fileKey (no colon), a token like `fileKey:` (empty node segment), or a URL lacking a non-empty `?node-id=` query param. The message points you at the two shapes that DO carry a node id.","triggerScenarios":"`figma asset <fileKey>` (bare key, no colon); `figma asset https://www.figma.com/design/ABC/Name` (file URL with no node-id query); `figma asset ABC:` (trailing colon, empty node). Node ids from a URL use dashes (e.g. 1:2) which parseFigmaRef normalizes via dashes->colons.","commonSituations":"Copying the file URL from the address bar instead of using 'Copy link' on a specific frame (which includes ?node-id=); manually stripping query parameters; passing a fileKey intended for a different subcommand.","solutions":["Right-click the frame in figma and 'Copy link' so the URL includes ?node-id=...","Pass fileKey:nodeId form, e.g. aBcDeF:1:2 (colons or dashes both accepted)","If batching, ensure every positional/comma-split ref resolves to a node id"],"exampleFix":"// before\nhyperframes figma asset aBcDeF\n// after\nhyperframes figma asset aBcDeF:1:2\n// or\nhyperframes figma asset 'https://www.figma.com/design/aBcDeF/Name?node-id=1-2'","handlingStrategy":"type-guard","validationCode":"import { parseFigmaRef } from '@hyperframes/core/figma';\nconst ref = parseFigmaRef(refInput);\nif (!ref.nodeId) {\n  throw new Error(`ref ${refInput} needs a node id; use fileKey:nodeId or a ?node-id= URL`);\n}","typeGuard":"import { parseFigmaRef } from '@hyperframes/core/figma';\nfunction refHasNodeId(refInput: string): boolean {\n  try { return Boolean(parseFigmaRef(refInput).nodeId); }\n  catch { return false; }\n}","tryCatchPattern":null,"preventionTips":["Always 'Copy link' from the frame in figma so the URL carries ?node-id=","Validate refs with parseFigmaRef before batching","Prefer fileKey:nodeId tokens for scriptability"],"tags":["figma","validation","asset","node-id","parse-figma-ref"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}