harry0703/MoneyPrinterTurbo · error · SoniloError
Sonilo returned an invalid service list
Error message
Sonilo returned an invalid service list
What it means
Raised during the Sonilo connection test when the /v1/account/services response's 'available_services' field is not a JSON list of strings. The client treats the service list as a hard protocol contract: a list whose elements include non-strings (nulls, numbers, nested objects) fails validation even if the overall payload parsed as JSON. It aborts before checking whether the video-to-music service is present.
Source
Thrown at app/services/sonilo.py:114
)
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:
raise SoniloError("Sonilo video-to-music service is not available for this key")
logger.info("Sonilo connection test succeeded")
return payload
def _remove_file(file_path: str) -> None:
"""尽力清理 Sonilo 中间文件,不覆盖调用方正在处理的原始异常。"""
if not file_path or not os.path.exists(file_path):
return
try:
os.remove(file_path)
except OSError as exc:
logger.warning(
f"failed to remove Sonilo temporary file: path={file_path}, error={exc}"View on GitHub (pinned to 1f9f19c202)
Solutions
- Inspect the raw response body (log response.text before parsing) and compare its available_services shape against the documented list-of-strings contract.
- If the provider changed the schema, update the parsing in app/services/sonilo.py:114 to accept the new shape (for example extract service ids from a list of objects) while keeping the strict list-of-strings path.
- If a proxy or gateway is mangling the response, fix or bypass the proxy so the JSON reaches the client intact.
- If this came from a test stub, correct the fixture to return a list containing the string video_to_music.
Example fix
// stub/fixture before
{"available_services": [{"id": "video_to_music"}]}
// after
{"available_services": ["video_to_music"]} Defensive patterns
Strategy: try-catch
Type guard
def is_valid_service_payload(payload: object) -> bool:
return (
isinstance(payload, dict)
and isinstance(payload.get("available_services"), list)
and all(isinstance(s, str) for s in payload["available_services"])
) Try / catch
try:
sonilo.test_connection()
except SoniloError as exc:
if "invalid service list" in str(exc):
# provider schema drift: inspect raw response, do not retry blindly
logger.error(f"Sonilo services schema changed: {exc}")
raise Prevention
- Pin the tested provider API version and re-run the connection test after any sonilo_base_url or provider change.
- Contract-test the services endpoint in CI against a recorded fixture shaped exactly like production.
When it happens
Trigger: Calling the Sonilo connection test (which GETs /v1/account/services) where the provider returns available_services as a list of objects like [{id: video_to_music}, null], or as a plain string instead of a list. Also triggered by API version changes that rename or restructure the field into a dict of quota objects.
Common situations: Provider ships an undocumented API revision; a proxy or gateway returns an HTML/JSON hybrid body that deserializes into unexpected shapes; a mock or stub server used in tests returns a simplified fixture without real string entries.
Related errors
- Sonilo returned an unexpected service response
- Sonilo returned an invalid service response
- Sonilo returned malformed streaming data
- Sonilo returned an invalid streaming event
- uploaded file must contain a decodable audio stream
AI-assisted analysis of harry0703/MoneyPrinterTurbo@1f9f19c202 (2026-08-14).
Data as JSON: /api/errors/6d831261e350114d.
Report an issue: GitHub.