{"record":{"id":"19f247452c29af23","repo":"wavetermdev/waveterm","slug":"job-not-started-19f247","errorCode":null,"errorMessage":"job not started","messagePattern":"job not started","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/jobmanager/mainserverconn.go","lineNumber":129,"sourceCode":"\tif !msc.SelfAuthenticated.Load() {\n\t\treturn nil, fmt.Errorf(\"not authenticated to server\")\n\t}\n\treturn WshCmdJobManager.PrepareConnect(msc, data)\n}\n\nfunc (msc *MainServerConn) JobStartStreamCommand(ctx context.Context, data wshrpc.CommandJobStartStreamData) error {\n\tif !msc.PeerAuthenticated.Load() {\n\t\treturn fmt.Errorf(\"not authenticated\")\n\t}\n\treturn WshCmdJobManager.StartStream(msc)\n}\n\nfunc (msc *MainServerConn) JobInputCommand(ctx context.Context, data wshrpc.CommandJobInputData) error {\n\tif !msc.PeerAuthenticated.Load() {\n\t\treturn fmt.Errorf(\"not authenticated\")\n\t}\n\tif !WshCmdJobManager.IsJobStarted() {\n\t\treturn fmt.Errorf(\"job not started\")\n\t}\n\n\tWshCmdJobManager.InputQueue.QueueItem(data.InputSessionId, data.SeqNum, data)\n\treturn nil\n}\n","sourceCodeStart":111,"sourceCodeEnd":135,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/jobmanager/mainserverconn.go#L111-L135","documentation":"JobInputCommand additionally requires that the job manager has an active job stream (IsJobStarted). If StartStream was never invoked, or the job already ended, input cannot be routed to any process and 'job not started' is returned.","triggerScenarios":"Calling JobInputCommand without a prior successful JobStartStreamCommand, or after the job stream has terminated (IsJobStarted returns false).","commonSituations":"User types into a terminal pane whose job died or was never launched; job ended while input was still queued from the client; a race where input is sent concurrently with job shutdown.","solutions":["Call JobStartStreamCommand first and confirm it succeeds before sending input","Check WshCmdJobManager.IsJobStarted() on the client side before sending input and surface 'job ended' to the user instead of forwarding keystrokes","Handle job-exit events to disable the input path when the stream terminates"],"exampleFix":"// before\nconn.JobInputCommand(ctx, data) // job may not be running\n// after\nif !conn.PeerAuthenticated.Load() { return fmt.Errorf(\"not authenticated\") }\nif !WshCmdJobManager.IsJobStarted() {\n    return fmt.Errorf(\"cannot send input: job is not running\")\n}\nreturn conn.JobInputCommand(ctx, data)","handlingStrategy":"validation","validationCode":"if !conn.PeerAuthenticated.Load() || !WshCmdJobManager.IsJobStarted() {\n    return fmt.Errorf(\"cannot send input: job not running\")\n}","typeGuard":null,"tryCatchPattern":"err := conn.JobInputCommand(ctx, data)\nif err != nil && strings.Contains(err.Error(), \"job not started\") {\n    // surface job-ended state to the user instead of retrying\n    ui.ShowJobEnded()\n}","preventionTips":["Track job lifecycle events and disable input when the stream ends","Call JobStartStreamCommand before wiring input handlers","Treat 'job not started' as terminal state, not a transient error"],"tags":["jobmanager","rpc","state"],"backgroundTag":"job-not-started","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}