{"record":{"id":"5346e0ea4e65c873","repo":"wavetermdev/waveterm","slug":"timeout-waiting-for-port","errorCode":null,"errorMessage":"timeout waiting for port","messagePattern":"timeout waiting for port","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/buildercontroller/buildercontroller.go","lineNumber":408,"sourceCode":"\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()\n\t\treturn nil, fmt.Errorf(\"cancelled while waiting for app port: %w\", ctx.Err())\n\t}\n}\n\nfunc (bc *BuilderController) handleBuildError(err error, resultCh chan<- *BuildResult) {\n\tbc.lock.Lock()\n\tdefer bc.lock.Unlock()\n\tbc.setStatus_nolock(BuilderStatus_Error, 0, 1, err.Error())\n\n\tif resultCh != nil {\n\t\tbuildOutput := \"\"\n\t\tif bc.outputBuffer != nil {\n\t\t\tlines := bc.outputBuffer.GetLines()\n\t\t\tbuildOutput = strings.Join(lines, \"\\n\")\n\t\t}\n\t\tselect {","sourceCodeStart":390,"sourceCodeEnd":426,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/buildercontroller/buildercontroller.go#L390-L426","documentation":"runBuilderApp enforces a hard 5-second timeout waiting for the builder subprocess to emit its listening port. If no port line appears in time, the process is killed and this error returned. It indicates the app started but never announced a port within the deadline.","triggerScenarios":"5s timer expires before the SetLineCallback detects a port line in the app's stdout/stderr output.","commonSituations":"Slow startup on cold caches or slow machines (first run, large compile); app writes its port in an unexpected format so the callback regex misses it; app blocks before binding (waiting on stdin, network, lock).","solutions":["Inspect captured output lines to see whether a port was printed but not matched, or not printed at all","Retry — transient slowness on first run often clears on subsequent builds","Check the port-detection regex/callback against the app's actual output format","Increase the 5s timeout if the target app legitimately starts slowly"],"exampleFix":"// before\ntimeout := time.NewTimer(5 * time.Second)\n// after\ntimeout := time.NewTimer(15 * time.Second) // allow slow first-run startups","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"process, err := bc.runBuilderApp(ctx, ...)\nif err != nil && err.Error() == \"timeout waiting for port\" {\n    // retry once; slow first runs often succeed on a warm cache\n    process, err = bc.runBuilderApp(ctx, ...)\n}","preventionTips":["Warm caches by running the build once before time-sensitive uses","Confirm the app's port-announcement output format matches the line callback matcher","Give the builder a larger timeout on slow machines or first runs","Avoid making the target app block on stdin/locks before it binds its port"],"tags":["timeout","subprocess","port-discovery","go"],"backgroundTag":"process-startup-timeout","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}