wavetermdev/waveterm · error
timeout waiting for port
Error message
timeout waiting for port
What it means
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.
Source
Thrown at pkg/buildercontroller/buildercontroller.go:408
case <-portChan:
default:
errChan <- fmt.Errorf("process died before emitting port")
}
}()
timeout := time.NewTimer(5 * time.Second)
defer timeout.Stop()
select {
case port := <-portChan:
process.Port = port
return process, nil
case err := <-errChan:
cmd.Process.Kill()
return nil, err
case <-timeout.C:
cmd.Process.Kill()
return nil, fmt.Errorf("timeout waiting for port")
case <-ctx.Done():
cmd.Process.Kill()
return nil, fmt.Errorf("cancelled while waiting for app port: %w", ctx.Err())
}
}
func (bc *BuilderController) handleBuildError(err error, resultCh chan<- *BuildResult) {
bc.lock.Lock()
defer bc.lock.Unlock()
bc.setStatus_nolock(BuilderStatus_Error, 0, 1, err.Error())
if resultCh != nil {
buildOutput := ""
if bc.outputBuffer != nil {
lines := bc.outputBuffer.GetLines()
buildOutput = strings.Join(lines, "\n")
}
select {View on GitHub (pinned to a4447c1563)
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
Example fix
// before timeout := time.NewTimer(5 * time.Second) // after timeout := time.NewTimer(15 * time.Second) // allow slow first-run startups
Defensive patterns
Strategy: retry
Try / catch
process, err := bc.runBuilderApp(ctx, ...)
if err != nil && err.Error() == "timeout waiting for port" {
// retry once; slow first runs often succeed on a warm cache
process, err = bc.runBuilderApp(ctx, ...)
} Prevention
- 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
When it happens
Trigger: 5s timer expires before the SetLineCallback detects a port line in the app's stdout/stderr output.
Common situations: 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).
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- process died before emitting port
- getting file info: %w
- failed to create stdout pipe: %w
- failed to create stderr pipe: %w
- failed to create stdin pipe: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/5346e0ea4e65c873.
Report an issue: GitHub.