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

  1. Call resolveHostRef again passing the host id (the second field shown in the message) instead of the name
  2. List available hosts and rename one via its config so names are unique
  3. 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

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


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)