amir20/dozzle · error
no container matching
Error message
no container matching %q found across all connected hosts; call find_containers to list available containers
What it means
The strict (write-path) resolver found zero candidate containers across all connected hosts, and no host was scoped, so it refuses with this message pointing callers at find_containers. Write actions never fall back to ambiguous or stopped containers.
Solutions
- Run find_containers to list available containers and copy the exact id
- Use the full container id rather than a name or short prefix
- Check the target host is connected (list_hosts); a disconnected host hides its containers
- If a stopped container is intended, start it or resolve via the read path first
Example fix
// before
restartContainer({container_id: "myapp"}) // no match
// after
const cs = await findContainers({name: "myapp"})
restartContainer({container_id: cs[0].id}) Defensive patterns
Strategy: validation
Validate before calling
const cs = await findContainers({}); const match = cs.find(c => c.id === ref || c.name === ref && c.state === 'running'); if (!match) throw new Error('no running container matching ' + ref); Type guard
null
Try / catch
try { await restartContainer({container_id: ref}) } catch (e) { if (/no container matching/.test(e.message)) { const cs = await findContainers({}); console.warn('candidates:', cs.map(c => c.id)); } } Prevention
- Copy ids from find_containers rather than typing names
- Remember write actions refuse stopped Swarm corpse containers
- Confirm the host is connected before acting
When it happens
Trigger: Calling executeContainerAction or executeUpdateContainer with a container_id that matches nothing: a typo'd name, an id from a removed container, or a short Swarm task name whose matches are all stopped (stopped corpses are excluded from writes).
Common situations: Docker Swarm redeploys leaving old task containers that were later pruned; container removed between discovery and action; case-sensitive name mismatch or missing dev.dozzle.name label.
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
- no host matching found; call list_hosts to see available…
- matches multiple containers: . To act on the right one
- container not found
- notifications are not configured on this host
- update failed
AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07).
Data as JSON: /api/errors/a147872c5fe33914.
Report an issue: GitHub.
Appendix: source
Thrown at internal/cloud/tools_resolve.go:63
// id or name).
func resolveContainerRef(containerRef, hostRef string, deps ToolDeps) (hostID, containerID string, err error) {
tier, trimmedHostRef, scopedHostID, hostNames, err := matchContainerTier(containerRef, hostRef, deps)
if err != nil {
return "", "", err
}
switch len(tier) {
case 0:
// No tier matched. When an explicit host was given (and resolved to a
// real host id) but the listing produced no match — e.g. a host returned
// a partial error and was omitted from ListAllContainers — pass the
// reference straight through to FindContainer's direct lookup, exactly as
// before this resolver existed. This guarantees id-based callers never
// regress.
if scopedHostID != "" {
return scopedHostID, strings.TrimSpace(containerRef), nil
}
return "", "", fmt.Errorf("no container matching %q found across all connected hosts; call find_containers to list available containers", strings.TrimSpace(containerRef))
case 1:
return tier[0].Host, tier[0].ID, nil
default:
// Multiple matches. The usual benign cause is Docker Swarm (or plain
// restart churn) leaving stopped task containers behind across redeploys
// — the short name "svc.1" substring-matches every historical
// "svc.1.<taskid>" corpse alongside the one live task. When exactly one
// candidate is running it is the unambiguous live referent, so resolve to
// it rather than make the caller hunt for an id. We still refuse to
// choose between multiple *live* containers — that is the real ambiguity
// the write tools must never guess at.
if live := runningContainers(tier); len(live) == 1 {
return live[0].Host, live[0].ID, nil
}
return "", "", ambiguousError(strings.TrimSpace(containerRef), trimmedHostRef, tier, hostNames)
}
}
View on GitHub (pinned to d9463cbe21)