babysor/MockingBird · error · RuntimeError

/emotion-enhance failed: status={resp.status_code}, body={re

Error message

/emotion-enhance failed: status={resp.status_code}, body={resp.text}

What it means

Raised by call_emotion_enhance in noiz_tts.py when the Noiz TTS /emotion-enhance HTTP endpoint returns a non-200 status. This is a remote API failure: the request reached the server but was rejected (auth, bad request, or server error). The response body is included to identify the cause.

Source

Thrown at skills/speak/scripts/noiz_tts.py:44

        canonical = base64.b64encode(decoded).decode("ascii").rstrip("=")
        if decoded and canonical == key.rstrip("="):
            return key
    except binascii.Error:
        pass
    return base64.b64encode(key.encode("utf-8")).decode("ascii")


def call_emotion_enhance(
    base_url: str, api_key: str, text: str, timeout: int
) -> str:
    resp = requests.post(
        f"{base_url.rstrip('/')}/emotion-enhance",
        headers={"Authorization": api_key, "Content-Type": "application/json"},
        json={"text": text},
        timeout=timeout,
    )
    if resp.status_code != 200:
        raise RuntimeError(
            f"/emotion-enhance failed: status={resp.status_code}, body={resp.text}"
        )
    enhanced = resp.json().get("data", {}).get("emotion_enhance")
    if not enhanced:
        raise RuntimeError(f"/emotion-enhance returned no data: {resp.text}")
    return enhanced


def synthesize(
    base_url: str,
    api_key: str,
    text: str,
    voice_id: Optional[str],
    reference_audio: Optional[Path],
    output_format: str,
    speed: float,
    emo: Optional[str],
    target_lang: Optional[str],

View on GitHub (pinned to 28dc5e14f1)

Solutions

  1. Check the status code and body in the message: 401/403 → fix API key, 404 → fix base_url
  2. Verify base_url matches the documented Noiz API host and has no trailing path mistakes
  3. Retry with backoff for 5xx/429 responses
  4. If body mentions text limits, shorten or sanitize the input text

Example fix

# before
resp = requests.post(url, headers={"Authorization": api_key}, json={"text": text}, timeout=timeout)
# after (retry transient failures)
for attempt in range(3):
    resp = requests.post(url, headers={"Authorization": api_key}, json={"text": text}, timeout=timeout)
    if resp.status_code < 500:
        break
    time.sleep(2 ** attempt)
Defensive patterns

Strategy: retry

Validate before calling

import requests
def check_noiz_service(base_url, api_key, timeout=10):
    r = requests.get(f"{base_url.rstrip('/')}/health", headers={"Authorization": api_key}, timeout=timeout)
    return r.status_code == 200

Try / catch

try:
    enhanced = call_emotion_enhance(base_url, key, text, timeout)
except RuntimeError as e:
    if 'status=5' in str(e) or 'status=429' in str(e):
        time.sleep(2); enhanced = call_emotion_enhance(base_url, key, text, timeout)
    else:
        raise

Prevention

When it happens

Trigger: POST {base_url}/emotion-enhance with Authorization header and json={"text": ...} returns 401/403 (bad API key), 404 (wrong base_url), 400 (empty/oversized text), or 5xx (server overload).

Common situations: Wrong or expired NOIZ_API_KEY, base_url pointing at the wrong host/path, network proxy returning 4xx/5xx, or the service being temporarily down.

Related errors


AI-assisted analysis of babysor/MockingBird@28dc5e14f1 (2026-08-27). Data as JSON: /api/errors/182d2c1d126e9c96. Report an issue: GitHub.