wavetermdev/waveterm · error

failed to get job: %w

Error message

failed to get job: %w

What it means

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.

Source

Thrown at pkg/jobcontroller/jobcontroller.go:146

	}, nil)
	wshclient.EventSubCommand(rpcClient, wps.SubscriptionRequest{
		Event:     wps.Event_ConnChange,
		AllScopes: true,
	}, nil)
	wshclient.EventSubCommand(rpcClient, wps.SubscriptionRequest{
		Event:     wps.Event_BlockClose,
		AllScopes: true,
	}, nil)
}

func isJobManagerRunning(job *waveobj.Job) bool {
	return job.JobManagerStatus == JobManagerStatus_Running
}

func GetJobManagerStatus(ctx context.Context, jobId string) (string, error) {
	job, err := wstore.DBGet[*waveobj.Job](ctx, jobId)
	if err != nil {
		return "", fmt.Errorf("failed to get job: %w", err)
	}
	if job == nil {
		return JobManagerStatus_Done, nil
	}
	return job.JobManagerStatus, nil
}

func GetAllJobManagerStatus(ctx context.Context) ([]*wshrpc.JobManagerStatusUpdate, error) {
	allJobs, err := wstore.DBGetAllObjsByType[*waveobj.Job](ctx, waveobj.OType_Job)
	if err != nil {
		return nil, fmt.Errorf("failed to get jobs: %w", err)
	}

	var statuses []*wshrpc.JobManagerStatusUpdate
	for _, job := range allJobs {
		statuses = append(statuses, &wshrpc.JobManagerStatusUpdate{
			JobId:            job.OID,
			JobManagerStatus: job.JobManagerStatus,

View on GitHub (pinned to a4447c1563)

Solutions

  1. Log and inspect the wrapped inner error (%w) to identify the wstore failure cause
  2. Retry GetJobManagerStatus with a fresh, non-canceled context
  3. Check DB file health/permissions in the wave data directory
  4. If the job may not exist, treat nil/DBGet failure distinctly and fall back to JobManagerStatus_Done

Example fix

// before
status, err := jobcontroller.GetJobManagerStatus(ctx, jobId)
if err != nil {
	return err
}
// after
status, err := jobcontroller.GetJobManagerStatus(ctx, jobId)
if err != nil {
	if errors.Is(ctx.Err(), context.Canceled) {
		return nil
	}
	log.Printf("job status lookup failed, defaulting to Done: %v", err)
	status = jobcontroller.JobManagerStatus_Done
}
Defensive patterns

Strategy: try-catch

Validate before calling

if ctx.Err() != nil {
	return errors.New("context already canceled; skip job status lookup")
}
job, _ := wstore.DBGet[*waveobj.Job](ctx, jobId)
if job == nil { /* will be treated as Done, no error */ }

Type guard

func jobRecordLoadable(ctx context.Context, jobId string) bool {
	return ctx.Err() == nil && jobId != ""
}

Try / catch

status, err := jobcontroller.GetJobManagerStatus(ctx, jobId)
if err != nil {
	var ctxErr = context.Canceled
	if errors.As(err, &ctxErr) { return nil }
	log.Printf("status lookup failed: %v", err)
	status = jobcontroller.JobManagerStatus_Done
}

Prevention

When it happens

Trigger: 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.

Common situations: Wave DB file locked or corrupted; calling from a shutdown path where the context was already canceled; transient disk errors during heavy I/O.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/2d941006c1574d7c. Report an issue: GitHub.