{"record":{"id":"2d941006c1574d7c","repo":"wavetermdev/waveterm","slug":"failed-to-get-job-w","errorCode":null,"errorMessage":"failed to get job: %w","messagePattern":"failed to get job: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/jobcontroller/jobcontroller.go","lineNumber":146,"sourceCode":"\t}, nil)\n\twshclient.EventSubCommand(rpcClient, wps.SubscriptionRequest{\n\t\tEvent:     wps.Event_ConnChange,\n\t\tAllScopes: true,\n\t}, nil)\n\twshclient.EventSubCommand(rpcClient, wps.SubscriptionRequest{\n\t\tEvent:     wps.Event_BlockClose,\n\t\tAllScopes: true,\n\t}, nil)\n}\n\nfunc isJobManagerRunning(job *waveobj.Job) bool {\n\treturn job.JobManagerStatus == JobManagerStatus_Running\n}\n\nfunc GetJobManagerStatus(ctx context.Context, jobId string) (string, error) {\n\tjob, err := wstore.DBGet[*waveobj.Job](ctx, jobId)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to get job: %w\", err)\n\t}\n\tif job == nil {\n\t\treturn JobManagerStatus_Done, nil\n\t}\n\treturn job.JobManagerStatus, nil\n}\n\nfunc GetAllJobManagerStatus(ctx context.Context) ([]*wshrpc.JobManagerStatusUpdate, error) {\n\tallJobs, err := wstore.DBGetAllObjsByType[*waveobj.Job](ctx, waveobj.OType_Job)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get jobs: %w\", err)\n\t}\n\n\tvar statuses []*wshrpc.JobManagerStatusUpdate\n\tfor _, job := range allJobs {\n\t\tstatuses = append(statuses, &wshrpc.JobManagerStatusUpdate{\n\t\t\tJobId:            job.OID,\n\t\t\tJobManagerStatus: job.JobManagerStatus,","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/jobcontroller/jobcontroller.go#L128-L164","documentation":"GetJobManagerStatus looks up a waveobj.Job in wstore by jobId and returns its manager status. This error wraps any underlying wstore database failure encountered while fetching the job record, distinct from a missing job (which returns JobManagerStatus_Done). It indicates the DBGet call itself failed, e.g. corrupted DB or context cancellation.","triggerScenarios":"Calling GetJobManagerStatus (directly or via getJobStatus_withlock / Start) with a jobId when wstore.DBGet fails — DB backend I/O error, context canceled/expired, or store not initialized.","commonSituations":"Wave DB file locked or corrupted; calling from a shutdown path where the context was already canceled; transient disk errors during heavy I/O.","solutions":["Log and inspect the wrapped inner error (%w) to identify the wstore failure cause","Retry GetJobManagerStatus with a fresh, non-canceled context","Check DB file health/permissions in the wave data directory","If the job may not exist, treat nil/DBGet failure distinctly and fall back to JobManagerStatus_Done"],"exampleFix":"// before\nstatus, err := jobcontroller.GetJobManagerStatus(ctx, jobId)\nif err != nil {\n\treturn err\n}\n// after\nstatus, err := jobcontroller.GetJobManagerStatus(ctx, jobId)\nif err != nil {\n\tif errors.Is(ctx.Err(), context.Canceled) {\n\t\treturn nil\n\t}\n\tlog.Printf(\"job status lookup failed, defaulting to Done: %v\", err)\n\tstatus = jobcontroller.JobManagerStatus_Done\n}","handlingStrategy":"try-catch","validationCode":"if ctx.Err() != nil {\n\treturn errors.New(\"context already canceled; skip job status lookup\")\n}\njob, _ := wstore.DBGet[*waveobj.Job](ctx, jobId)\nif job == nil { /* will be treated as Done, no error */ }","typeGuard":"func jobRecordLoadable(ctx context.Context, jobId string) bool {\n\treturn ctx.Err() == nil && jobId != \"\"\n}","tryCatchPattern":"status, err := jobcontroller.GetJobManagerStatus(ctx, jobId)\nif err != nil {\n\tvar ctxErr = context.Canceled\n\tif errors.As(err, &ctxErr) { return nil }\n\tlog.Printf(\"status lookup failed: %v\", err)\n\tstatus = jobcontroller.JobManagerStatus_Done\n}","preventionTips":["Always pass a live context and check ctx.Err() before DB calls","Log the wrapped inner error, not just the outer message","Handle nil job (Done) and DB failure as separate paths","Monitor DB health in the wave data directory"],"tags":["database","wstore","job-controller"],"backgroundTag":"database-read-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}