containerd/containerd · error

can't find sandbox for TaskExit event: %w

Error message

can't find sandbox for TaskExit event: %w

What it means

HandleEvent returns this when neither the container store nor the sandbox store can resolve a TaskExit event's ID — and the sandbox lookup failed with an error other than NotFound. Since NotFound from both stores means the ID is unknown and is silently ignored, a non-NotFound error here indicates the sandbox store lookup machinery itself failed.

Source

Thrown at internal/cri/server/events.go:347

		log.L.Infof("TaskExit event %+v", e)
		// Use ID instead of ContainerID to rule out TaskExit event for exec.
		cntr, err := ce.c.containerStore.Get(e.ID)
		if err == nil {
			if err := ce.c.handleContainerExit(ctx, e, cntr, cntr.SandboxID); err != nil {
				return fmt.Errorf("failed to handle container TaskExit event: %w", err)
			}
			return nil
		} else if !errdefs.IsNotFound(err) {
			return fmt.Errorf("can't find container for TaskExit event: %w", err)
		}
		sb, err := ce.c.sandboxStore.Get(e.ID)
		if err == nil {
			if err := ce.c.handleSandboxExit(ctx, sb, e.ExitStatus, e.ExitedAt.AsTime()); err != nil {
				return fmt.Errorf("failed to handle sandbox TaskExit event: %w", err)
			}
			return nil
		} else if !errdefs.IsNotFound(err) {
			return fmt.Errorf("can't find sandbox for TaskExit event: %w", err)
		}
		return nil
	case *eventtypes.SandboxExit:
		log.L.Infof("SandboxExit event %+v", e)
		sb, err := ce.c.sandboxStore.Get(e.GetSandboxID())
		if err == nil {
			if err := ce.c.handleSandboxExit(ctx, sb, e.ExitStatus, e.ExitedAt.AsTime()); err != nil {
				return fmt.Errorf("failed to handle sandbox TaskExit event: %w", err)
			}
			return nil
		} else if !errdefs.IsNotFound(err) {
			return fmt.Errorf("can't find sandbox for TaskExit event: %w", err)
		}
		return nil
	case *eventtypes.TaskOOM:
		log.L.Infof("TaskOOM event %+v", e)
		// For TaskOOM, we only care which container it belongs to.
		cntr, err := ce.c.containerStore.Get(e.ContainerID)

View on GitHub (pinned to 4246446a2b)

Solutions

  1. Check containerd daemon logs for sandbox store / bolt errors
  2. Restart containerd; the backoff monitor will redeliver the event
  3. Inspect wrapped error chain for the underlying store cause
  4. If persistent, inspect the containerd root metadata DB integrity
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: exit early on NotFound from container store, then guard sandbox lookup:
cntr, err := containerStore.Get(e.ID)
if errdefs.IsNotFound(err) {
    sb, serr := sandboxStore.Get(e.ID)
    if serr != nil && !errdefs.IsNotFound(serr) {
        return fmt.Errorf("can't find sandbox for TaskExit event: %w", serr)
    }
}

Type guard

func isSandboxLookupFailure(err error) bool {
    return err != nil && !errdefs.IsNotFound(err)
}

Try / catch

if err := HandleEvent(ev); err != nil {
    if isSandboxLookupFailure(err) {
        log.L.WithError(err).Errorf("sandbox store failure; restart may be required")
    }
    // NotFound from both stores is intentionally ignored
}

Prevention

When it happens

Trigger: containerStore.Get(e.ID) returns NotFound, then sandboxStore.Get(e.ID) returns a non-NotFound error (metadata DB failure, transport error, store corruption) while handling *eventtypes.TaskExit.

Common situations: containerd metadata bolt DB failure under load; daemon shutdown mid-event; store corruption after crash; upgrade leaving inconsistent store state.

Related errors


AI-assisted analysis of containerd/containerd@4246446a2b (2026-09-02). Data as JSON: /api/errors/5cc3fc9a27366281. Report an issue: GitHub.