calesthio/OpenMontage · error · RuntimeError

HTTP {http_status}, code {code}: {message}{hint}

Error message

HTTP {http_status}, code {code}: {message}{hint}

What it means

Template for the central Doubao error raiser _raise_for_doubao_error. It fires when either HTTP status >= 400 or payload code != 20000000, formatting status, code, message, and a diagnostic hint derived from the message text. Hints map known failure strings to fixes: 'load grant' → X-Api-Key flow, 'speaker permission denied' → voice authorization, 'quota exceeded' → quota/concurrency, 'unsupported additions explicit language' → drop that field.

Source

Thrown at tools/audio/doubao_tts.py:376

                return query_data
            if status == 3:
                raise RuntimeError(f"Doubao task failed: {query_data.get('message', 'unknown error')}")
        raise TimeoutError(f"Doubao task did not finish within {timeout_seconds} seconds")

    @staticmethod
    def _json_or_raise(response: Any) -> dict[str, Any]:
        try:
            return response.json()
        except ValueError as exc:
            raise RuntimeError(f"Non-JSON response from Doubao API: HTTP {response.status_code}") from exc

    def _raise_for_doubao_error(self, http_status: int, payload: dict[str, Any]) -> None:
        code = payload.get("code")
        if http_status < 400 and code == 20000000:
            return
        message = payload.get("message", "unknown error")
        hint = self._diagnostic_hint(message)
        raise RuntimeError(f"HTTP {http_status}, code {code}: {message}{hint}")

    @staticmethod
    def _diagnostic_hint(message: str) -> str:
        lowered = message.lower()
        if "load grant" in lowered or "requested grant not found" in lowered:
            return " (check DOUBAO_SPEECH_API_KEY and use the new-console X-Api-Key flow)"
        if "speaker permission denied" in lowered or "access denied" in lowered:
            return " (check voice_id/DOUBAO_SPEECH_VOICE_TYPE and voice authorization)"
        if "quota exceeded" in lowered:
            return " (check quota, concurrency, or remaining character package)"
        if "unsupported additions explicit language" in lowered:
            return " (do not pass additions.explicit_language for this endpoint)"
        return ""

    @staticmethod
    def _safe_error(exc: Exception) -> str:
        # Avoid ever echoing request headers or secrets in user-visible errors.
        return str(exc).replace(os.environ.get("DOUBAO_SPEECH_API_KEY", ""), "[redacted]")

View on GitHub (pinned to 95e1c3d0ab)

Solutions

  1. Parse the appended hint — it names the exact fix for the four known message classes
  2. For load-grant errors: re-issue the key from the new Volcengine console and send it via X-Api-Key header
  3. For voice errors: confirm voice_id/DOUBAO_SPEECH_VOICE_TYPE is authorized for this account
  4. For quota errors: top up the character package or reduce concurrency
  5. Otherwise quote code + message to Volcengine support
Defensive patterns

Strategy: try-catch

Try / catch

try:
    result = doubao_tool.execute(inputs)
except RuntimeError as e:
    # message already carries a targeted hint; surface it to the user verbatim
    show_user_error(str(e))

Prevention

When it happens

Trigger: Any API-level rejection on submit or query: bad/expired DOUBAO_SPEECH_API_KEY, unauthorized voice_id, exhausted quota or concurrency, explicit_language passed to an endpoint that forbids it.

Common situations: Old bearer-token key used with the new-console X-Api-Key flow; voice_type cloned in a different account; free character package depleted mid-batch; SDK version mismatch adding unsupported fields.

Related errors


AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15). Data as JSON: /api/errors/ec1f99fcb0af14e3. Report an issue: GitHub.