{"record":{"id":"ca02db48284b47bc","repo":"wavetermdev/waveterm","slug":"timeout-waiting-for-job-manager-to-start","errorCode":null,"errorMessage":"timeout waiting for job manager to start","messagePattern":"timeout waiting for job manager to start","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshrpc/wshremote/wshremote_job.go","lineNumber":245,"sourceCode":"\t\t}\n\t}()\n\n\ttimeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second)\n\tdefer cancel()\n\n\tlog.Printf(\"RemoteStartJobCommand: waiting for start signal\\n\")\n\tselect {\n\tcase err := <-startCh:\n\t\tif err != nil {\n\t\t\tcmd.Process.Kill()\n\t\t\tlog.Printf(\"RemoteStartJobCommand: error from start signal: %v\\n\", err)\n\t\t\treturn nil, err\n\t\t}\n\t\tlog.Printf(\"RemoteStartJobCommand: received start signal\\n\")\n\tcase <-timeoutCtx.Done():\n\t\tcmd.Process.Kill()\n\t\tlog.Printf(\"RemoteStartJobCommand: timeout waiting for start signal\\n\")\n\t\treturn nil, fmt.Errorf(\"timeout waiting for job manager to start\")\n\t}\n\n\tgo func() {\n\t\tcmd.Wait()\n\t}()\n\n\tjobRouteId, cleanup, err := impl.connectToJobManager(ctx, data.JobId, data.MainServerJwtToken)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcombinedEnv := make(map[string]string)\n\tfor k, v := range impl.InitialEnv {\n\t\tcombinedEnv[k] = v\n\t}\n\tfor k, v := range data.Env {\n\t\tcombinedEnv[k] = v\n\t}","sourceCodeStart":227,"sourceCodeEnd":263,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshrpc/wshremote/wshremote_job.go#L227-L263","documentation":"RemoteStartJobCommand waits up to 5 seconds (context.WithTimeout) for the 'Wave-JobManagerStart' signal on the ready pipe. If the timeout fires first, the child is killed and this error is returned — the jobmanager started but never became ready.","triggerScenarios":"The jobmanager process runs but hangs before emitting the start signal: slow startup (heavy load, cold filesystem), a hang waiting on network/auth setup, or a binary that never writes the signal to fd 3.","commonSituations":"Overloaded or swapping remote host where wsh startup exceeds 5s; hung connection handshake inside the child; version mismatch causing the child to wait for input that never comes.","solutions":["Check remote host load and I/O latency; retry under lighter load","Inspect stderr logs to find where the jobmanager is stalling","Update the wsh binary via 'wsh init' to rule out protocol mismatch","If startups are legitimately slow, increase the 5s timeout in RemoteStartJobCommand"],"exampleFix":"// before\ntimeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second)\n// after\ntimeoutCtx, cancel := context.WithTimeout(ctx, 30*time.Second)","handlingStrategy":"retry","validationCode":"// check the remote can start wsh promptly\nstart := time.Now()\nout, err := exec.Command(wshPath, \"--version\").CombinedOutput()\nif err != nil || time.Since(start) > 3*time.Second {\n    return fmt.Errorf(\"wsh slow or broken on remote (%.1fs): %v\", time.Since(start).Seconds(), err)\n}","typeGuard":null,"tryCatchPattern":"rtn, err := server.RemoteStartJobCommand(ctx, data)\nif err != nil {\n    if strings.Contains(err.Error(), \"timeout waiting for job manager\") {\n        // retry under lighter load or after increasing the startup timeout\n    }\n    return err\n}","preventionTips":["Monitor remote host load; avoid job starts during heavy load","Raise the 5s startup timeout if hosts are legitimately slow","Keep wsh versions in sync so the child never blocks waiting on unknown input"],"tags":["timeout","process-startup","ready-signal","job-manager"],"backgroundTag":"process-start-timeout","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}