amir20/dozzle · error

container not found

Error message

container not found: %w

What it means

executeStreamLogs resolves the target container through HostService.FindContainer before streaming; any lookup failure (unknown id, container on wrong host, stopped/removed) is wrapped as 'container not found'. The tool responds with this error instead of opening a log stream.

Solutions

  1. Re-list containers to get the current id and retry with the fresh id
  2. Verify host_id matches the host the container runs on (resolve with the host id from an ambiguity message)
  3. Check the container still exists and is running (docker ps on that host)

Example fix

// before
FindContainer(hostID, "my-web-app", labels) // name, stale
// after
FindContainer(hostID, "a1b2c3d4e5f6", labels) // fresh id from listing
Defensive patterns

Strategy: retry

Validate before calling

containers := listContainers(hostID)
exists := false
for _, c := range containers { if c.ID == containerID { exists = true } }
// only stream if exists

Try / catch

if err != nil && strings.Contains(err.Error(), "container not found") {
  // re-list containers, pick fresh id, retry once
}

Prevention

When it happens

Trigger: executeStreamLogs calls deps.HostService.FindContainer(hostID, containerID, deps.Labels) and receives a non-nil error: id not present on the given host, host unknown, or label filtering excludes the container.

Common situations: LLM passing a container name where the id is expected; container recreated so its id changed after restart/redeploy; wrong host_id pairing; container removed before the stream started.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07). Data as JSON: /api/errors/3627ae71d9d1b845. Report an issue: GitHub.

Appendix: source

Thrown at internal/cloud/tools_stream.go:82

func executeStreamLogs(ctx context.Context, requestID string, argsJSON string, deps ToolDeps, send streamSender) error {
	args, re, err := parseStreamArgs(argsJSON)
	if err != nil {
		return err
	}

	// Read-only: resolve an ambiguous name in one shot instead of erroring. note
	// is non-empty when the name resolved to one of several candidates; it is
	// surfaced once, on the first emitted batch, so the model learns the pick and
	// its siblings without a round-trip and without repeating on every batch.
	hostID, containerID, note, err := resolveContainerRefRead(args.ContainerID, args.Host, deps)
	if err != nil {
		return err
	}

	cs, err := deps.HostService.FindContainer(hostID, containerID, deps.Labels)
	if err != nil {
		return fmt.Errorf("container not found: %w", err)
	}

	events := make(chan *container.LogEvent, 100)

	// Both backends already cap a follow stream at the last N lines (Docker
	// Tail: 100, k8s TailLines: 500), so `from` only decides how many of those
	// survive the since-filter. now-30s threw nearly all of them away, which
	// left a quiet container showing an empty pane until it happened to log
	// something. Anchoring at the container's start lets the tail cap do the
	// work: last N lines, then live. Same value the web UI streams from, see
	// streamLogs in internal/web/logs.go.
	from := cs.Container.StartedAt
	if from.IsZero() {
		from = time.Now().Add(-30 * time.Second)
	}

	go func() {
		defer close(events)

View on GitHub (pinned to d9463cbe21)