{"record":{"id":"3627ae71d9d1b845","repo":"amir20/dozzle","slug":"container-not-found-w-3627ae","errorCode":null,"errorMessage":"container not found: %w","messagePattern":"container not found: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cloud/tools_stream.go","lineNumber":82,"sourceCode":"\nfunc executeStreamLogs(ctx context.Context, requestID string, argsJSON string, deps ToolDeps, send streamSender) error {\n\targs, re, err := parseStreamArgs(argsJSON)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Read-only: resolve an ambiguous name in one shot instead of erroring. note\n\t// is non-empty when the name resolved to one of several candidates; it is\n\t// surfaced once, on the first emitted batch, so the model learns the pick and\n\t// its siblings without a round-trip and without repeating on every batch.\n\thostID, containerID, note, err := resolveContainerRefRead(args.ContainerID, args.Host, deps)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tcs, err := deps.HostService.FindContainer(hostID, containerID, deps.Labels)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"container not found: %w\", err)\n\t}\n\n\tevents := make(chan *container.LogEvent, 100)\n\n\t// Both backends already cap a follow stream at the last N lines (Docker\n\t// Tail: 100, k8s TailLines: 500), so `from` only decides how many of those\n\t// survive the since-filter. now-30s threw nearly all of them away, which\n\t// left a quiet container showing an empty pane until it happened to log\n\t// something. Anchoring at the container's start lets the tail cap do the\n\t// work: last N lines, then live. Same value the web UI streams from, see\n\t// streamLogs in internal/web/logs.go.\n\tfrom := cs.Container.StartedAt\n\tif from.IsZero() {\n\t\tfrom = time.Now().Add(-30 * time.Second)\n\t}\n\n\tgo func() {\n\t\tdefer close(events)","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/amir20/dozzle/blob/d9463cbe21874e44ab79db6fa63e746ca7d22928/internal/cloud/tools_stream.go#L64-L100","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Re-list containers to get the current id and retry with the fresh id","Verify host_id matches the host the container runs on (resolve with the host id from an ambiguity message)","Check the container still exists and is running (docker ps on that host)"],"exampleFix":"// before\nFindContainer(hostID, \"my-web-app\", labels) // name, stale\n// after\nFindContainer(hostID, \"a1b2c3d4e5f6\", labels) // fresh id from listing","handlingStrategy":"retry","validationCode":"containers := listContainers(hostID)\nexists := false\nfor _, c := range containers { if c.ID == containerID { exists = true } }\n// only stream if exists","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"container not found\") {\n  // re-list containers, pick fresh id, retry once\n}","preventionTips":["Re-resolve container ids after restarts/redeploys (ids change)","Pair the id with the correct host_id","Confirm the container is running before opening a stream"],"tags":["cloud-tools","logs","resource-not-found"],"backgroundTag":"resource-not-found","analyzedSha":"d9463cbe21874e44ab79db6fa63e746ca7d22928","analyzedAt":"2026-09-07T10:08:55.855Z","contentChangedAt":"2026-09-07T10:08:55.855Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}