{"record":{"id":"aeb04f2b8f85c18f","repo":"microsoft/typescript-go","slug":"getnodeid-requires-a-remotenode","errorCode":null,"errorMessage":"getNodeId requires a RemoteNode","messagePattern":"getNodeId requires a RemoteNode","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"_packages/native-preview/src/api/node/node.ts","lineNumber":358,"sourceCode":"}\r\n\r\n/**\r\n * Decode binary-encoded AST data into a Node.\r\n * Works for any binary-encoded node, including synthetic nodes\r\n * (e.g. from typeToTypeNode) that don't have a source file.\r\n */\r\nexport function decodeNode(data: Uint8Array): Node {\r\n    const sf = new RemoteSourceFile(data, new Wtf8Decoder());\r\n    return sf as unknown as Node;\r\n}\r\n\r\n/**\r\n * Get the unique ID string for a remote node.\r\n * Throws if the node is not a RemoteNode (i.e. not decoded from binary data).\r\n */\r\nexport function getNodeId(node: Node): string {\r\n    if (!(node instanceof RemoteNode)) {\r\n        throw new Error(\"getNodeId requires a RemoteNode\");\r\n    }\r\n    return node.id;\r\n}\r\n","sourceCodeStart":340,"sourceCodeEnd":362,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/_packages/native-preview/src/api/node/node.ts#L340-L362","documentation":"getNodeId only accepts a RemoteNode, i.e. a node that was decoded from binary data produced by the native (tsgo) server via decodeNode() or obtained through the native-preview API. Any other Node implementation (a locally constructed AST node, a plain object cast to Node, or a node from a different decoder) lacks the remote id backing store, so the function refuses it. The throw is an intentional type check because Node is a structural interface that cannot distinguish remote nodes statically.","triggerScenarios":"Calling getNodeId(node) where node came from anything other than decodeNode(new Uint8Array(...)) or an API-returned node: e.g. getNodeId({ kind: SyntaxKind.Identifier } as Node), getNodeId on a node built by your own parser, or a node obtained from the old/async wire format that is not a RemoteNode instance.","commonSituations":"Mixing node objects from different APIs (checker-returned nodes vs locally fabricated stubs), upgrading @typescript/native-preview versions where the RemoteNode class identity changed (two copies of the package loaded), or test code creating fake Node objects.","solutions":["Only call getNodeId on nodes returned by decodeNode() or by the native API itself","If you fabricated the node, track its identity yourself instead of relying on getNodeId","Check for duplicate @typescript/native-preview installs (npm ls) if the node really is remote but instanceof fails — two module copies break instanceof"],"exampleFix":"// before\nconst id = getNodeId({ kind: 75 } as Node); // throws\n\n// after\nimport { decodeNode, getNodeId } from \"@typescript/native-preview\";\nconst node = decodeNode(binaryFromServer);\nconst id = getNodeId(node);","handlingStrategy":"type-guard","validationCode":"import { RemoteNode } from \"...remote-node-module\";\nconst isRemote = (n: Node): boolean => n instanceof RemoteNode;","typeGuard":"function isRemoteNode(n: Node): boolean {\n  // RemoteNode is the class produced by decodeNode; instanceof is the definitive check\n  return typeof (n as { id?: unknown }).id === \"string\" && n.constructor?.name === \"RemoteNode\";\n}","tryCatchPattern":"try { id = getNodeId(node); } catch (e) { if ((e as Error).message.includes(\"requires a RemoteNode\")) { /* fall back to your own node identity */ } else throw e; }","preventionTips":["Only pass nodes from decodeNode() or API returns into getNodeId","Keep a single copy of @typescript/native-preview installed so instanceof checks hold","Track identity for nodes you construct yourself instead of using getNodeId"],"tags":["typescript","node","type-guard","native-preview"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}