wavetermdev/waveterm · error

block not found: %s

Error message

block not found: %s

What it means

GetBlockJobStatus returns this error when wstore.DBGet successfully completes but returns a nil block, meaning no waveobj.Block exists with the given blockId. It is a caller-supplied-identifier problem, not a storage failure.

Source

Thrown at pkg/jobcontroller/jobcontroller.go:177

	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)
	}
	if job == nil {
		return data, nil
	}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Verify the blockId is a valid existing block OID before calling
  2. Check whether the block was closed/deleted and re-create it if needed
  3. Use a live BlockId from the current block registry
  4. Treat as expected when handling delete/close races and skip silently

Example fix

// before
status, err := jobcontroller.GetBlockJobStatus(ctx, staleBlockId)
if err != nil {
	return err
}
// after
status, err := jobcontroller.GetBlockJobStatus(ctx, blockId)
if err != nil && strings.HasPrefix(err.Error(), "block not found") {
	return nil // block closed; nothing to report
} else if err != nil {
	return err
}
Defensive patterns

Strategy: validation

Validate before calling

block, err := wstore.DBGet[*waveobj.Block](ctx, blockId)
if block == nil {
	return fmt.Errorf("skip: block %s does not exist", blockId)
}
_ = err

Type guard

func isBlockNotFoundErr(err error) bool {
	return err != nil && strings.Contains(err.Error(), "block not found")
}

Try / catch

status, err := jobcontroller.GetBlockJobStatus(ctx, blockId)
if err != nil {
	if isBlockNotFoundErr(err) {
		return nil // expected race: block closed
	}
	return err
}

Prevention

When it happens

Trigger: Calling GetBlockJobStatus (or BlockJobStatusCommand / SendBlockJobStatusEvent) with a blockId that does not exist in wstore — stale block reference, block already closed/deleted, or a typo'd/fabricated ID.

Common situations: Frontend caches a blockId after the block was closed; event races where the block is deleted between enqueue and lookup; passing an OID of the wrong object type.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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