{"record":{"id":"9423f60ae5d0ee02","repo":"microsoft/typescript-go","slug":"error-calling-callback-name-errmsg","errorCode":null,"errorMessage":"Error calling callback `${name}`: ${errMsg}","messagePattern":"Error calling callback `(.+?)`: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"_packages/native-preview/src/api/syncChannel.ts","lineNumber":366,"sourceCode":"            throw new Error(`no callback named \\`${name}\\` found`);\r\n        }\r\n\r\n        try {\r\n            const result = cb(name, payload.toString(\"utf-8\"));\r\n            this.writeTuple(\r\n                MSG_CALL_RESPONSE,\r\n                Buffer.from(name, \"utf-8\"),\r\n                Buffer.from(result, \"utf-8\"),\r\n            );\r\n        }\r\n        catch (e: unknown) {\r\n            const errMsg = String(e instanceof Error ? e.message : e).trim();\r\n            this.writeTuple(\r\n                MSG_CALL_ERROR,\r\n                Buffer.from(name, \"utf-8\"),\r\n                Buffer.from(errMsg, \"utf-8\"),\r\n            );\r\n            throw new Error(`Error calling callback \\`${name}\\`: ${errMsg}`);\r\n        }\r\n    }\r\n\r\n    // ── MessagePack tuple write ─────────────────────────────────────\r\n\r\n    /**\r\n     * Write a complete [type, name, payload] tuple in as few writeSync\r\n     * calls as possible.  For messages that fit in the pre-allocated\r\n     * write buffer (64 KB), everything is assembled and sent in a single\r\n     * syscall.  Larger messages use two syscalls: one for the header\r\n     * portion and one for the payload data.\r\n     */\r\n    private writeTuple(type: number, name: Buffer, payload: Buffer | Uint8Array | string): void {\r\n        const nameLen = name.length;\r\n        const payloadIsString = typeof payload === \"string\";\r\n        const payloadLen = payloadIsString ? Buffer.byteLength(payload, \"utf-8\") : payload.length;\r\n        const nameHdrSize = binHeaderSize(nameLen);\r\n        const payloadHdrSize = binHeaderSize(payloadLen);\r","sourceCodeStart":348,"sourceCodeEnd":384,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/_packages/native-preview/src/api/syncChannel.ts#L348-L384","documentation":"A registered host-side callback ran but threw an exception. The channel reports the failure to the child via MSG_CALL_ERROR and then re-throws in the parent, deliberately treating a failed callback as unrecoverable to match the native libsyncrpc addon's behavior — the pending request loop aborts.","triggerScenarios":"Any exception inside a registerCallback handler: fs.readFileSync on a missing/permission-denied path, JSON.parse of a malformed argument, or a bug in user callback code.","commonSituations":"Host callback doing filesystem access for the child when the file was deleted mid-session, EACCES on restricted paths, or a custom callback that assumes an argument format the child changed between versions.","solutions":["Fix the underlying exception reported in errMsg (the message names the callback and the cause)","Make the callback defensive: return a well-defined error value instead of throwing when the child protocol allows it","Validate inputs (path strings) before touching fs","If the failure is transient (EBUSY on Windows), retry the fs operation inside the callback"],"exampleFix":"// before\nchannel.registerCallback('readFile', (name, path) => fs.readFileSync(path, 'utf8')); // ENOENT throws\n\n// after\nchannel.registerCallback('readFile', (name, path) => {\n  try {\n    return fs.readFileSync(path, 'utf8');\n  } catch (e) {\n    return ''; // or encode an error the child understands\n  }\n});","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { channel.call('geterr', payload); } catch (e) { if (e.message.startsWith('Error calling callback')) { const cause = e.message.split(': ').slice(1).join(': '); /* fix the fs/permission cause, then restart the channel */ } throw e; }","preventionTips":["Never let a registered callback throw for expected conditions — return error encodings instead","Wrap fs calls inside callbacks and surface actionable messages","Test callbacks against missing/locked files during development"],"tags":["rpc","callbacks","filesystem","unrecoverable"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}