{"record":{"id":"f304b8fa6495599f","repo":"wavetermdev/waveterm","slug":"process-died-before-emitting-port","errorCode":null,"errorMessage":"process died before emitting port","messagePattern":"process died before emitting port","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/buildercontroller/buildercontroller.go","lineNumber":392,"sourceCode":"\t\tStdinWriter: stdinPipe,\n\t\tWaitCh:      waitCh,\n\t}\n\n\tgo func() {\n\t\tprocess.WaitRtn = cmd.Wait()\n\t\tclose(waitCh)\n\t}()\n\n\tgo bc.outputBuffer.ReadAll(stdoutPipe)\n\tgo bc.outputBuffer.ReadAll(stderrPipe)\n\n\terrChan := make(chan error, 1)\n\tgo func() {\n\t\t<-process.WaitCh\n\t\tselect {\n\t\tcase <-portChan:\n\t\tdefault:\n\t\t\terrChan <- fmt.Errorf(\"process died before emitting port\")\n\t\t}\n\t}()\n\n\ttimeout := time.NewTimer(5 * time.Second)\n\tdefer timeout.Stop()\n\n\tselect {\n\tcase port := <-portChan:\n\t\tprocess.Port = port\n\t\treturn process, nil\n\tcase err := <-errChan:\n\t\tcmd.Process.Kill()\n\t\treturn nil, err\n\tcase <-timeout.C:\n\t\tcmd.Process.Kill()\n\t\treturn nil, fmt.Errorf(\"timeout waiting for port\")\n\tcase <-ctx.Done():\n\t\tcmd.Process.Kill()","sourceCodeStart":374,"sourceCodeEnd":410,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/buildercontroller/buildercontroller.go#L374-L410","documentation":"After starting the builder app, runBuilderApp waits up to 5 seconds for the subprocess to emit its port via a callback into portChan. If the process's WaitCh fires (process exited) before any port was received, this error is returned and the process is killed. It means the builder app crashed or exited early without announcing a port.","triggerScenarios":"Builder subprocess exits within 5s without writing a recognized port line to stdout/stderr — e.g. binary crash, bad args, missing runtime deps, immediate compile error in the app being run.","commonSituations":"Corrupted or stale builder binary; the underlying app panics at startup; incompatible protocol so the port regex never matches while the process exits for another reason.","solutions":["Check the builder output buffer/logs for the real crash message (panic, missing dependency)","Rebuild the builder binary ('make build') to eliminate a corrupted/stale artifact","Run the app being executed directly to reproduce its startup error","Verify required env vars and files the app needs are passed via builderEnv"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"process, err := bc.runBuilderApp(ctx, ...)\nif err != nil && err.Error() == \"process died before emitting port\" {\n    // surface builder output buffer contents to the user for the real cause\n    return fmt.Errorf(\"builder exited early: %w (see output for crash details)\", err)\n}","preventionTips":["Rebuild the builder binary after version changes to avoid stale/corrupt artifacts","Test the target app's startup standalone before running it through the builder","Keep builderEnv complete (required env vars for the app) so it does not exit immediately","Retain and display subprocess output — it holds the real crash reason"],"tags":["subprocess","process-exit","port-discovery","go"],"backgroundTag":"process-exited-before-ready","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}