{"record":{"id":"c039cdd31920ece9","repo":"microsoft/typescript-go","slug":"no-callback-named-name-found","errorCode":null,"errorMessage":"no callback named `${name}` found","messagePattern":"no callback named `(.+?)` found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"_packages/native-preview/src/api/syncChannel.ts","lineNumber":348,"sourceCode":"\r\n    /**\r\n     * Handle an incoming MSG_CALL from the child process.\r\n     *\r\n     * After sending the error response back to the child, this method\r\n     * intentionally re-throws to abort the caller's request loop.\r\n     * A failed callback is treated as unrecoverable to match the\r\n     * behavior of the native libsyncrpc addon.\r\n     */\r\n    private handleCall(name: string, payload: Buffer): void {\r\n        const cb = this.callbacks.get(name);\r\n        if (!cb) {\r\n            const errMsg = `unknown callback: \\`${name}\\`. Please make sure to register it on the JavaScript side before invoking it.`;\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(`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","sourceCodeStart":330,"sourceCodeEnd":366,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/_packages/native-preview/src/api/syncChannel.ts#L330-L366","documentation":"The child process (Go tsserver) sent an MSG_CALL asking the JS host to execute a host-side callback (e.g. readFile), but no callback was registered under that name on the SyncChannel. The channel first writes a MSG_CALL_ERROR back to the child, then throws in the parent's read loop, aborting the pending request.","triggerScenarios":"Spawning the child and issuing requests without first calling channel.registerCallback(name, cb) for every operation the child may delegate; a version mismatch where the child knows a callback name the host never registers; a typo in the name passed to registerCallback.","commonSituations":"Custom hosts that build their own SyncChannel instead of using the ready-made client in api/sync/client.ts (which registers readFile, fileExists, directoryExists, getAccessibleEntries, realpath, writeFile); upgrading the child without updating host registration code.","solutions":["Use the provided client wrapper (api/sync/client.ts) which registers all callbacks automatically","If driving SyncChannel manually, call registerCallback for each name: 'readFile', 'fileExists', 'directoryExists', 'getAccessibleEntries', 'realpath', 'writeFile' before the first request","Verify the callback name spelling matches exactly (case-sensitive)","Match host package and child binary versions so the callback set agrees"],"exampleFix":"// before\nconst channel = new SyncChannel(childPath, args);\nconst res = channel.call('geterr', ...); // child asks for 'readFile' -> throws\n\n// after\nchannel.registerCallback('readFile', (name, path) => fs.readFileSync(path, 'utf8'));\nchannel.registerCallback('fileExists', (name, path) => fs.existsSync(path) ? 'true' : 'false');\nconst res = channel.call('geterr', ...);","handlingStrategy":"validation","validationCode":"const REQUIRED = ['readFile','fileExists','directoryExists','getAccessibleEntries','realpath','writeFile'];\nfor (const name of REQUIRED) {\n  if (!channel.callbacks.has(name)) channel.registerCallback(name, makeDefaultCallback(name));\n}","typeGuard":"function hasAllCallbacks(channel: SyncChannel): boolean {\n  return ['readFile','fileExists','directoryExists','getAccessibleEntries','realpath','writeFile']\n    .every(n => channel.callbacks.has(n));\n}","tryCatchPattern":"try { channel.call(method, payload); } catch (e) { if (/no callback named `(.+)` found/.test(e.message)) { /* register the named callback, then restart session */ } throw e; }","preventionTips":["Prefer the bundled client in api/sync/client.ts over hand-wiring SyncChannel","Register callbacks immediately after construction, before any request","Keep host/child versions in lockstep so callback sets match"],"tags":["rpc","callbacks","native-preview","initialization"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}