{"record":{"id":"5d1315a3ec4e0191","repo":"wavetermdev/waveterm","slug":"failed-to-reconnect-to-job-w","errorCode":null,"errorMessage":"failed to reconnect to job: %w","messagePattern":"failed to reconnect to job: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/blockcontroller/durableshellcontroller.go","lineNumber":186,"sourceCode":"\t\tfsErr := filestore.WFS.MakeFile(ctx, dsc.BlockId, wavebase.BlockFile_Term, nil, wshrpc.FileOpts{MaxSize: DefaultTermMaxFileSize, Circular: true})\n\t\tif fsErr != nil && fsErr != fs.ErrExist {\n\t\t\treturn fmt.Errorf(\"error creating block term file: %w\", fsErr)\n\t\t}\n\t\tnewJobId, err := dsc.startNewJob(ctx, blockMeta, dsc.ConnName, rtOpts)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to start new job: %w\", err)\n\t\t}\n\t\tjobId = newJobId\n\t}\n\n\tdsc.WithLock(func() {\n\t\tdsc.JobId = jobId\n\t\tdsc.sendUpdate_withlock()\n\t})\n\n\terr = jobcontroller.ReconnectJob(ctx, jobId, rtOpts)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to reconnect to job: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc (dsc *DurableShellController) Stop(graceful bool, newStatus string, destroy bool) {\n\tif !destroy {\n\t\treturn\n\t}\n\tjobId := dsc.getJobId()\n\tif jobId == \"\" {\n\t\treturn\n\t}\n\tctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\n\tdefer cancel()\n\tjobcontroller.TerminateAndDetachJob(ctx, jobId)\n}\n","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/blockcontroller/durableshellcontroller.go#L168-L204","documentation":"DurableShellController.Start wraps any error from jobcontroller.ReconnectJob, which attempts to reattach the block to a previously created durable remote shell job. It means the existing job could not be resumed — the job may have died, its domain socket is gone, or the connection to the remote is down. The block's durable shell cannot be restored to its prior state.","triggerScenarios":"Calling Start on a block whose meta indicates a durable remote shell with an existing JobId, when ReconnectJob fails — e.g. the SSH connection is down, the remote wsh server/socket no longer exists, or the job was already terminated on the remote side.","commonSituations":"Laptop wakes from sleep and the SSH connection dropped; the remote machine rebooted and the shell job is gone; stale JobId persisted in block state after a remote crash; connserver on the remote is not running.","solutions":["Check/refresh the SSH connection to the remote host (test with a plain ssh command).","Restart the block or call Start with force to create a fresh job instead of reconnecting.","Inspect the wrapped inner error (%w) for the root cause (socket not found vs auth vs network).","If the remote was rebooted, accept the session is lost and start a new shell."],"exampleFix":"// before\nerr := controller.Start(ctx, blockMeta, rtOpts, false) // tries reconnect, fails\n// after\nif err := controller.Start(ctx, blockMeta, rtOpts, false); err != nil {\n    // force a brand-new job instead of reconnecting to a dead one\n    err = controller.Start(ctx, blockMeta, rtOpts, true)\n}","handlingStrategy":"retry","validationCode":"// best-effort pre-check: is the remote reachable?\nif conn := conncontroller.MaybeGetConn(opts); conn == nil || conn.DeriveConnStatus().Status != conncontroller.Status_Connected {\n    return fmt.Errorf(\"remote not connected; reconnect before Start\")\n}","typeGuard":null,"tryCatchPattern":"if err := dsc.Start(ctx, meta, rtOpts, false); err != nil {\n    var root = errors.Unwrap(err) // inspect ReconnectJob cause\n    log.Printf(\"reconnect failed (%v); forcing new job\", root)\n    err = dsc.Start(ctx, meta, rtOpts, true) // fallback to fresh job\n}","preventionTips":["Check connection status before attempting reconnect","Treat persistent reconnect failure as a signal to force a new job","Persist JobId state carefully and clear it when the remote reboots","Surface the unwrapped cause to the user for diagnosis"],"tags":["ssh","remote","durable-shell","reconnect"],"backgroundTag":"remote-shell-reconnect-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}