HKUDS/nanobot · error · ValueError

{error}

Error message

{error}

What it means

In _probe_tcp(), the pre-connection target check failed: resolve_url_target() returned ok=False with an error string, which is re-raised verbatim as ValueError. This is a generic guard raising another resolver's message; the input at fault is the host/port combination whose DNS resolution or SSRF policy check failed (e.g. resolves to loopback/private IP while allow_loopback is False).

Solutions

  1. Use a resolvable, policy-compliant host for the channel being validated
  2. Pass allow_loopback=True only when a loopback target is intentional (local testing)
  3. Read the embedded resolver message to see whether it was DNS failure or an SSRF policy rejection
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at nanobot/channels/validation.py:367 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of HKUDS/nanobot@42f37dc4c0 (2026-08-26). Data as JSON: /api/errors/9918dbb087ae1a4d. Report an issue: GitHub.

Appendix: source

Thrown at nanobot/channels/validation.py:367

    return cast(dict[str, Any], data) if isinstance(data, dict) else {}


def _http_post(url: str, *, headers: dict[str, str] | None = None) -> dict[str, Any]:
    with httpx.Client(timeout=_TIMEOUT_SECONDS) as client:
        response = client.post(url, headers=headers)
        response.raise_for_status()
        data = response.json()
    return cast(dict[str, Any], data) if isinstance(data, dict) else {}


def _probe_tcp(host: str, port: int, *, allow_loopback: bool = False) -> None:
    url_host = host if ":" not in host or host.startswith("[") else f"[{host}]"
    ok, error, resolved_ips = resolve_url_target(
        f"http://{url_host}:{port}/",
        allow_loopback=allow_loopback,
    )
    if not ok:
        raise ValueError(error)

    context = ssl.create_default_context()
    last_error: OSError | None = None
    for target_ip in resolved_ips:
        try:
            with socket.create_connection((target_ip, port), timeout=_TIMEOUT_SECONDS) as sock:
                if port in {465, 993, 995}:
                    with context.wrap_socket(sock, server_hostname=host.strip("[]")):
                        return
                return
        except OSError as exc:
            last_error = exc
    if last_error is not None:
        raise last_error
    raise OSError(f"Could not resolve {host}")


# Public helpers for channel-owned validators. Keeping response shaping here lets

View on GitHub (pinned to 42f37dc4c0)