harry0703/MoneyPrinterTurbo · error · SoniloError

Sonilo API key is required

Error message

Sonilo API key is required

What it means

Raised by sonilo.test_connection() when get_api_key() returns an empty string. The key resolution order is config.app['sonilo_api_key'] then the SONILO_API_KEY environment variable; when both are empty/whitespace, the BGM connection test cannot run. This is a pre-flight guard, not an API error.

Source

Thrown at app/services/sonilo.py:90

    """
    return service_id.strip().lower().replace("-", "_")


def _safe_response_error(response: requests.Response) -> str:
    """仅保留简短响应信息,既方便定位又避免异常页面污染日志。"""
    body = (response.text or "").strip().replace("\n", " ")[:500]
    return body or response.reason or "request failed"


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):

View on GitHub (pinned to 1f9f19c202)

Solutions

  1. Set sonilo_api_key in config.toml under [app], or export SONILO_API_KEY in the service environment, then re-run the connection test
  2. If using WebUI, save the key through the Sonilo settings field so config.app persists it
  3. Verify no leading/trailing whitespace-only value was saved (it strips to empty and still fails)
  4. Check is_enabled() before invoking BGM flows so tasks degrade gracefully instead of erroring

Example fix

# shell
export SONILO_API_KEY="sk-live-..."

# or config.toml
[app]
sonilo_api_key = "sk-live-..."
Defensive patterns

Strategy: validation

Validate before calling

from app.services import sonilo

if not sonilo.is_enabled():
    # skip BGM/Sonilo flows instead of invoking test_connection()
    disable_sonilo_bgm()

Try / catch

except SoniloError as e: if 'API key is required' in str(e): non-retryable — collect the key from the user (config or SONILO_API_KEY) before retrying

Prevention

When it happens

Trigger: Invoking sonilo.test_connection() (from WebUI connection test or task startup) while config.toml has no sonilo_api_key, the WebUI field is empty, and the SONILO_API_KEY env var is unset or whitespace-only.

Common situations: User enabled Sonilo BGM generation but never entered a key; key was cleared when config.toml was re-saved from the WebUI; service/deployment env lost SONILO_API_KEY between restarts; key saved under a misspelled config key.

Related errors


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