harry0703/MoneyPrinterTurbo · error · SoniloError

Sonilo connection failed ({response.status_code}): {_safe_re

Error message

Sonilo connection failed ({response.status_code}): {_safe_response_error(response)}

What it means

Raised by sonilo.test_connection() when the services-list request completes but response.ok is False (HTTP status >= 400). The message includes the status code and up to 500 characters of the response body via _safe_response_error, so the exact server rejection (auth, quota, permission) is visible.

Source

Thrown at app/services/sonilo.py:100

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
    }
    if VIDEO_TO_MUSIC_SERVICE_ID not in normalized_services:

View on GitHub (pinned to 1f9f19c202)

Solutions

  1. Read the status code and body in the message: 401/403 → fix sonilo_api_key; 404 → fix sonilo_base_url; 429 → wait before retesting; 5xx → retry later
  2. Regenerate the key in the Sonilo console if revoked, update config.toml/WebUI, re-run test_connection()
  3. Confirm the key's subscription includes the video-to-music service (the endpoint lists services scoped to the key)
  4. If a custom base_url is set, drop it to use the default https://api.sonilo.com
Defensive patterns

Strategy: try-catch

Try / catch

except SoniloError as e: parse the embedded status — retry only on 429/5xx with backoff; 401/403 → fix the key; 404 → fix base_url; surface _safe_response_error body to the user

Prevention

When it happens

Trigger: GET {base_url}/v1/account/services returning 401/403 (invalid or revoked Sonilo API key, key lacking permission), 404 (wrong base_url or outdated SERVICES_PATH), 429 (rate limit), or 5xx (Sonilo server error).

Common situations: Expired or mistyped Sonolo API key; key from a different product tier without video_to_music access; sonilo_base_url pointing to a staging/gateway host with different routes; hitting rate limits during repeated connection tests; Sonilo-side incidents returning 502/503.

Related errors


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