Skip to content

wizard exits mid-run with "InformationalError: socket idle timeout" #1198

Description

@posthog

The wizard ends a run without warning. The terminal prints InformationalError: socket idle timeout and the process exits with code 1, leaving whatever the user was doing unfinished. On runs that stop at an interactive prompt, the prompt paints and then disappears within about a second, so it reads as the prompt itself crashing. Expected behavior is that a background transport error is logged or ignored, and the run continues.

The error is not raised by wizard code. It comes from a Node timer, and the wizard has no handler for it, so it terminates the process.

How to reproduce

  1. Run npx @posthog/wizard@2.71.0 self-driving (or upload-source-maps) in a project.
  2. Let the run reach a point where it waits after a network call, such as an agent step or an interactive prompt.
  3. When Node's bundled undici raises InformationalError: socket idle timeout on an idle HTTP/2 session, roughly 5 seconds after the last request completes, the process prints the error and exits.

Step 3 depends on the Node build, so it does not reproduce on every machine. The fatal handling does reproduce deterministically:

const { PostHog } = require('posthog-node')
new PostHog('<project key>', { host: '<host>', enableExceptionAutocapture: true })
process.stdin.resume()
setInterval(() => console.log('alive'), 400)
setTimeout(() => { throw new Error('boom') }, 600)

That exits with code 1 at 600ms. Adding any process.on('uncaughtException') listener, or turning autocapture off, keeps it alive.

Additional context

From https://us.posthog.com/project/2/support/tickets/70634

Why it happens

src/utils/analytics.ts constructs the PostHog client with enableExceptionAutocapture: true. In the published posthog-node build, the autocapture handler counts the uncaughtException listeners that are not its own, and when that count is zero it treats the exception as fatal:

async onFatalError(exception) {
  console.error(exception)
  await this.client.shutdown(SHUTDOWN_TIMEOUT)
  globalThis.process.exit(1)
}

The wizard registers no uncaughtException listener anywhere in src/, so that count is always zero and every uncaught error is fatal, whatever raised it.

For this particular error the captured stack is process.processTimers to listOnTimeout to Timeout.onHttp2SessionIdleTimeout, in Node's bundled undici. undici's onHttp2SessionIdleTimeout constructs new InformationalError('socket idle timeout') and calls util.destroy(socket, err). With nothing listening for that error it surfaces on uncaughtException.

The await shutdown() before process.exit(1) leaves a short window where the Ink render loop can still paint. That is why the last thing a user sees can be a prompt that appears and vanishes, and why the exception is sometimes recorded just before the prompt it appears to have killed.

Where it shows up

Every release from 2.58.0 through 2.71.0, since early August. Overwhelmingly on the self-driving command, with a smaller share on upload-source-maps. The screen at the time of the exit varies, which fits an error timed off the last network call rather than off anything on screen.

Suggested approaches

  1. Register a process.on('uncaughtException') handler in the wizard. That alone stops posthog-node from ending the process, and lets the wizard decide what is genuinely fatal and print something a user can act on.
  2. Decide separately whether a benign transport error should end a run at all.
  3. Capture the Node version in wizard telemetry. It is not recorded today, which makes it hard to confirm which Node builds raise this. allowH2 is off by default in undici 7, which Node 24 bundles, and on by default in undici 8, so the exposure likely tracks the Node version.

Related work

The open PRs that filter transport errors at analytics.captureException (#1023, #1182) do not cover this. Autocapture reports through posthog-node directly and never passes through that wrapper, and the process exit happens regardless of whether the event is dropped.

Debug info

  • Wizard version: [please provide]
  • Node version (node -v): [please provide]
  • Operating system and terminal: [please provide]

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1Well-defined; high impactbugSomething isn't workinghelp wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions