{"record":{"id":"42b42c20fb70a70c","repo":"calesthio/OpenMontage","slug":"tokenhub-api-error-code-code-message-message-42b42c","errorCode":null,"errorMessage":"TokenHub API error: code={code}, message={message}","messagePattern":"TokenHub API error: code=(.+?), message=(.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"tools/video/hunyuan_cloud_video.py","lineNumber":528,"sourceCode":"        \"\"\"Parse JSON response body or raise with HTTP status.\"\"\"\n        try:\n            return response.json()\n        except ValueError as exc:\n            raise RuntimeError(\n                f\"Non-JSON response from TokenHub API: HTTP {response.status_code}\"\n            ) from exc\n\n    @staticmethod\n    def _check_response(payload: dict[str, Any]) -> None:\n        \"\"\"Check the TokenHub API response for errors.\n\n        TokenHub returns errors at the top level with an ``error`` field.\n        \"\"\"\n        error = payload.get(\"error\")\n        if error:\n            message = error.get(\"message\", \"unknown error\")\n            code = error.get(\"code\", error.get(\"type\", \"unknown\"))\n            raise RuntimeError(\n                f\"TokenHub API error: code={code}, message={message}\"\n            )\n","sourceCodeStart":510,"sourceCodeEnd":531,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/video/hunyuan_cloud_video.py#L510-L531","documentation":"Raised by _check_response when a TokenHub JSON payload carries a top-level 'error' object. This is the provider's structured error channel (mirroring OpenAI-style errors): the message and code/type from that object are embedded in the exception. It fires on both submit and poll responses, catching auth failures, invalid requests, quota issues, and model errors.","triggerScenarios":"Any TokenHub API call whose 200/4xx JSON body includes {error: {message, code|type}} — bad/expired TENCENT_TOKENHUB_API_KEY, unknown model name, invalid parameters, insufficient balance, or rate limiting surfaced through the error envelope.","commonSituations":"API key typo or revocation; account balance exhausted on TokenHub; requesting a model id the key is not entitled to; parameter validation failures (bad duration/resolution combos); note the code falls back to the 'type' field when 'code' is absent.","solutions":["Read code= and message= in the exception — they name the exact provider-side problem.","For auth errors (invalid api key), verify TENCENT_TOKENHUB_API_KEY is set correctly in the environment.","For quota/balance errors, top up or wait for the quota window to reset.","For invalid-parameter errors, align duration/resolution/model with TokenHub's documented allowed values.","Retry only for rate-limit codes, with backoff."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import os\n\ndef precheck_tokenhub_env() -> None:\n    key = os.environ.get(\"TENCENT_TOKENHUB_API_KEY\")\n    if not key:\n        raise RuntimeError(\"TENCENT_TOKENHUB_API_KEY not set\")\n    if inputs.get(\"model\") not in ALLOWED_MODELS:\n        raise ValueError(f\"unknown model: {inputs.get('model')}\")","typeGuard":null,"tryCatchPattern":"try:\n    result = hunyuan_cloud_video(inputs)\nexcept RuntimeError as e:\n    if \"TokenHub API error\" in str(e):\n        code = str(e).split(\"code=\")[1].split(\",\")[0]\n        if code in (\"rate_limit\", \"429\", \"too_many_requests\"):\n            time.sleep(30); result = hunyuan_cloud_video(inputs)\n        elif \"key\" in str(e).lower() or code in (\"401\", \"invalid_api_key\"):\n            raise ConfigError(\"fix TENCENT_TOKENHUB_API_KEY\") from e\n        else:\n            raise\n    else:\n        raise","preventionTips":["Set and sanity-check TENCENT_TOKENHUB_API_KEY before batch runs.","Whitelist allowed model ids in your config to catch typos early.","Parse the embedded code/message and only retry rate-limit errors."],"tags":["hunyuan","tokenhub","provider-error","auth","quota","api-contract"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}