amir20/dozzle · error
host name is ambiguous; matches: . Pass the host id instead
Error message
host name %q is ambiguous; matches: %s. Pass the host id instead
What it means
resolveHostRef accepts a host id or name; when a name matches more than one host it refuses to guess and lists every match as 'Name (id X)'. This is a cloud-tool resolution error meant for an LLM caller, so the message is intentionally actionable and tells it to re-issue with the host id.
Solutions
- Call resolveHostRef again passing the host id (the second field shown in the message) instead of the name
- List available hosts and rename one via its config so names are unique
- If the tool schema accepts host_id, supply host_id explicitly in the tool call arguments
Example fix
// before resolveHostRef(ctx, deps, "server") // after resolveHostRef(ctx, deps, "abc123") // id shown in the ambiguity message
Defensive patterns
Strategy: validation
Validate before calling
ids, names := listHosts(ctx, deps)
nameCounts := map[string]int{}
for _, h := range hosts { nameCounts[h.Name]++ }
func isUnambiguousHost(ref string, hosts []Host) bool {
for _, h := range hosts { if h.ID == ref { return true } }
n := 0
for _, h := range hosts { if h.Name == ref { n++ } }
return n == 1
} Type guard
func hostRefIsID(ref string, hosts []Host) bool {
for _, h := range hosts { if h.ID == ref { return true } }
return false
} Prevention
- Always pass host ids, not names, in cloud tool calls
- Keep host names unique across the deployment
- When an ambiguity message appears, reuse the (id X) value it prints
When it happens
Trigger: resolveHostRef is given a hostRef that is not a known id but matches >1 host by name; raised in the default branch after byName lookup returns multiple entries (len(byName) > 1). Called from matchContainerTier in the cloud tools pipeline.
Common situations: Two hosts registered with the same name (e.g. duplicate agent enrollment, Swarm nodes sharing a display name, a host re-added under an existing name). An LLM tool call passing 'server' or 'remote' where multiple hosts share that label.
Related errors
- no host matching found; call list_hosts to see available…
- matches multiple containers: . To act on the right one
- notifications are not configured on this host
- update failed
- unknown action
AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07).
Data as JSON: /api/errors/e40ba472cc367121.
Report an issue: GitHub.
Appendix: source
Thrown at internal/cloud/tools_resolve.go:231
for _, h := range hosts {
if h.ID == hostRef {
return h.ID, nil
}
if strings.EqualFold(h.Name, hostRef) {
byName = append(byName, h)
}
}
switch len(byName) {
case 0:
return "", fmt.Errorf("no host matching %q found; call list_hosts to see available hosts", hostRef)
case 1:
return byName[0].ID, nil
default:
names := make([]string, len(byName))
for i, h := range byName {
names[i] = fmt.Sprintf("%s (id %s)", h.Name, h.ID)
}
return "", fmt.Errorf("host name %q is ambiguous; matches: %s. Pass the host id instead", hostRef, strings.Join(names, "; "))
}
}
// ambiguousError builds an actionable error listing every candidate so the
// caller can re-issue the call unambiguously. The hint is tailored to the
// candidate set because the LLM reads it to choose its next action: when the
// candidates span multiple hosts, host_id disambiguates; when they all sit on
// one host, host_id is useless and only the exact id or full name will do.
func ambiguousError(containerRef, hostRef string, candidates []container.Container, hostNames map[string]string) error {
parts := make([]string, len(candidates))
sameHost := true
for i, c := range candidates {
parts[i] = fmt.Sprintf("%s (id %s, %s, on host %s)", c.Name, shortID(c.ID), describeState(c), resolveHostName(c.Host, hostNames))
if c.Host != candidates[0].Host {
sameHost = false
}
}
View on GitHub (pinned to d9463cbe21)