wavetermdev/waveterm · error

failed to get block: %w

Error message

failed to get block: %w

What it means

GetBlockJobStatus first fetches the waveobj.Block for blockId from wstore. This error wraps a DBGet failure for that block — a storage-layer error rather than a missing block (missing is reported separately as 'block not found').

Source

Thrown at pkg/jobcontroller/jobcontroller.go:174

	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,
		})
	}

	return statuses, nil
}

func GetBlockJobStatus(ctx context.Context, blockId string) (*wshrpc.BlockJobStatusData, error) {
	block, err := wstore.DBGet[*waveobj.Block](ctx, blockId)
	if err != nil {
		return nil, fmt.Errorf("failed to get block: %w", err)
	}
	if block == nil {
		return nil, fmt.Errorf("block not found: %s", blockId)
	}

	data := &wshrpc.BlockJobStatusData{
		BlockId:   blockId,
		VersionTs: blockJobStatusVersion.GetVersionTs(),
	}

	if block.JobId == "" {
		return data, nil
	}

	job, err := wstore.DBGet[*waveobj.Job](ctx, block.JobId)
	if err != nil {
		return nil, fmt.Errorf("failed to get job: %w", err)
	}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Inspect the wrapped inner error for the wstore cause
  2. Retry with a valid context
  3. Verify the wave DB integrity in the data directory
  4. For event senders, skip sending the event on transient failure

Example fix

// before
status, err := jobcontroller.GetBlockJobStatus(ctx, blockId)
if err != nil {
	panic(err)
}
// after
status, err := jobcontroller.GetBlockJobStatus(ctx, blockId)
if err != nil {
	log.Printf("block job status unavailable for %s: %v", blockId, err)
	return
}
Defensive patterns

Strategy: try-catch

Validate before calling

if ctx.Err() != nil {
	return errors.New("context canceled")
}
if blockId == "" {
	return errors.New("blockId is empty")
}

Type guard

func blockExists(ctx context.Context, blockId string) bool {
	b, err := wstore.DBGet[*waveobj.Block](ctx, blockId)
	return err == nil && b != nil
}

Try / catch

status, err := jobcontroller.GetBlockJobStatus(ctx, blockId)
if err != nil && !strings.HasPrefix(err.Error(), "block not found") {
	log.Printf("transient failure for block %s: %v", blockId, err)
	return
}

Prevention

When it happens

Trigger: Calling GetBlockJobStatus (directly or via SendBlockJobStatusEvent / BlockJobStatusCommand) when wstore.DBGet[*waveobj.Block] fails — DB I/O error, invalid/corrupted record data, canceled context.

Common situations: Querying a block while the DB is shutting down; corrupted block record; context canceled by an RPC timeout.

Related errors


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