microsoft/typescript-go · error · Error

no callback named `${name}` found

Error message

no callback named `${name}` found

What it means

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.

Source

Thrown at _packages/native-preview/src/api/syncChannel.ts:348

    /**
     * Handle an incoming MSG_CALL from the child process.
     *
     * After sending the error response back to the child, this method
     * intentionally re-throws to abort the caller's request loop.
     * A failed callback is treated as unrecoverable to match the
     * behavior of the native libsyncrpc addon.
     */
    private handleCall(name: string, payload: Buffer): void {
        const cb = this.callbacks.get(name);
        if (!cb) {
            const errMsg = `unknown callback: \`${name}\`. Please make sure to register it on the JavaScript side before invoking it.`;
            this.writeTuple(
                MSG_CALL_ERROR,
                Buffer.from(name, "utf-8"),
                Buffer.from(errMsg, "utf-8"),
            );
            throw new Error(`no callback named \`${name}\` found`);
        }

        try {
            const result = cb(name, payload.toString("utf-8"));
            this.writeTuple(
                MSG_CALL_RESPONSE,
                Buffer.from(name, "utf-8"),
                Buffer.from(result, "utf-8"),
            );
        }
        catch (e: unknown) {
            const errMsg = String(e instanceof Error ? e.message : e).trim();
            this.writeTuple(
                MSG_CALL_ERROR,
                Buffer.from(name, "utf-8"),
                Buffer.from(errMsg, "utf-8"),
            );
            throw new Error(`Error calling callback \`${name}\`: ${errMsg}`);

View on GitHub (pinned to 1bcfa18d79)

Solutions

  1. Use the provided client wrapper (api/sync/client.ts) which registers all callbacks automatically
  2. If driving SyncChannel manually, call registerCallback for each name: 'readFile', 'fileExists', 'directoryExists', 'getAccessibleEntries', 'realpath', 'writeFile' before the first request
  3. Verify the callback name spelling matches exactly (case-sensitive)
  4. Match host package and child binary versions so the callback set agrees

Example fix

// before
const channel = new SyncChannel(childPath, args);
const res = channel.call('geterr', ...); // child asks for 'readFile' -> throws

// after
channel.registerCallback('readFile', (name, path) => fs.readFileSync(path, 'utf8'));
channel.registerCallback('fileExists', (name, path) => fs.existsSync(path) ? 'true' : 'false');
const res = channel.call('geterr', ...);
Defensive patterns

Strategy: validation

Validate before calling

const REQUIRED = ['readFile','fileExists','directoryExists','getAccessibleEntries','realpath','writeFile'];
for (const name of REQUIRED) {
  if (!channel.callbacks.has(name)) channel.registerCallback(name, makeDefaultCallback(name));
}

Type guard

function hasAllCallbacks(channel: SyncChannel): boolean {
  return ['readFile','fileExists','directoryExists','getAccessibleEntries','realpath','writeFile']
    .every(n => channel.callbacks.has(n));
}

Try / catch

try { channel.call(method, payload); } catch (e) { if (/no callback named `(.+)` found/.test(e.message)) { /* register the named callback, then restart session */ } throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16). Data as JSON: /api/errors/c039cdd31920ece9. Report an issue: GitHub.