harry0703/MoneyPrinterTurbo · error · SoniloError

failed to connect to Sonilo: {exc}

Error message

failed to connect to Sonilo: {exc}

What it means

Raised by sonilo.test_connection() when the GET to {base_url}/v1/account/services fails with a requests.RequestException — DNS failure, connection refused, TLS error, or timeout (connect 15s / read 30s). The original exception text is embedded and chained with `from exc`, so the network cause is preserved.

Source

Thrown at app/services/sonilo.py:98


def test_connection() -> dict[str, Any]:
    """
    使用不消耗配乐额度的服务列表接口验证 API Key。

    返回原始 JSON 便于 UI 展示可用服务,但日志中绝不记录 Key 或请求头。
    """
    api_key = get_api_key()
    if not api_key:
        raise SoniloError("Sonilo API key is required")
    try:
        response = requests.get(
            f"{_base_url()}{SERVICES_PATH}",
            headers={"Authorization": f"Bearer {api_key}"},
            timeout=(15, 30),
        )
    except requests.RequestException as exc:
        raise SoniloError(f"failed to connect to Sonilo: {exc}") from exc
    if not response.ok:
        raise SoniloError(
            f"Sonilo connection failed ({response.status_code}): "
            f"{_safe_response_error(response)}"
        )
    try:
        payload = response.json()
    except ValueError as exc:
        raise SoniloError("Sonilo returned an invalid service response") from exc
    if not isinstance(payload, dict):
        raise SoniloError("Sonilo returned an unexpected service response")
    available_services = payload.get("available_services")
    if not isinstance(available_services, list) or not all(
        isinstance(service_id, str) for service_id in available_services
    ):
        raise SoniloError("Sonilo returned an invalid service list")
    normalized_services = {
        _normalize_service_id(service_id) for service_id in available_services

View on GitHub (pinned to 1f9f19c202)

Solutions

  1. Check sonilo_base_url in config.toml — it should be https://api.sonilo.com (or unset to use the default); fix typos
  2. Verify outbound connectivity from the same host/container: curl -v https://api.sonilo.com/v1/account/services
  3. Fix proxy/TLS env (HTTPS_PROXY, REQUESTS_CA_BUNDLE) if behind a corporate proxy; import the proxy CA or set tls_verify appropriately
  4. If Sonilo is down (check status page), retry later — the chained exc text distinguishes DNS vs timeout vs TLS
  5. Ensure container DNS works (docker network, /etc/resolv.conf) when running in k8s/compose

Example fix

# before (config.toml)
[app]
sonilo_base_url = "https://api.sonilo.com/typo"  # wrong path -> DNS/404 issues

# after
[app]
# omit sonilo_base_url entirely to use the default https://api.sonilo.com
Defensive patterns

Strategy: retry

Validate before calling

import socket, urllib.parse
host = urllib.parse.urlparse(_base_url()).hostname
socket.getaddrinfo(host, 443)  # fail fast on DNS/resolution problems

Try / catch

except SoniloError as e: if 'failed to connect' in str(e): retry with backoff for timeouts/short DNS blips; persistent failure → fix base_url/proxy/DNS; the chained `exc` names the root cause

Prevention

When it happens

Trigger: requests.get(f'{base_url}/v1/account/services', ...) raising ConnectionError (DNS/host unreachable), ConnectTimeout/ReadTimeout (slow or hanging Sonilo API), or SSLError — e.g. sonilo_base_url misconfigured, api.sonilo.com unreachable from the network, or a proxy interfering.

Common situations: sonilo_base_url typo in config.toml (wrong host, trailing path); container/deployment without outbound internet; corporate firewall or self-signed TLS interception blocking api.sonilo.com; Sonilo API outage; read timeout too short on high-latency links (the 30s test read timeout is fixed).

Related errors


AI-assisted analysis of harry0703/MoneyPrinterTurbo@1f9f19c202 (2026-08-14). Data as JSON: /api/errors/e555afe2723a5726. Report an issue: GitHub.