{"record":{"id":"0ef33857f8f3d740","repo":"HKUDS/DeepTutor","slug":"http-error-message-exc","errorCode":null,"errorMessage":"_http_error_message(exc)","messagePattern":"_http_error_message\\(exc\\)","errorType":"exception","errorClass":"MinerUError","httpStatus":null,"severity":"error","filePath":"deeptutor/services/parsing/engines/mineru/cloud.py","lineNumber":278,"sourceCode":"    **kwargs,\n) -> dict:\n    for attempt in range(2):\n        api_key = key_pool.next()\n        try:\n            response = request(\n                path,\n                timeout=_SUBMIT_TIMEOUT_SECONDS,\n                headers={\"Authorization\": f\"Bearer {api_key}\"},\n                **kwargs,\n            )\n            response.raise_for_status()\n            payload = response.json()\n        except httpx.HTTPStatusError as exc:\n            if exc.response.status_code == 429:\n                key_pool.mark_429(api_key)\n                if attempt == 0:\n                    continue\n            raise MinerUError(_http_error_message(exc)) from exc\n        except httpx.HTTPError as exc:\n            raise MinerUError(f\"MinerU API request failed: {exc}\") from exc\n        _check_code(payload)\n        return payload\n    raise MinerUError(\"MinerU API key rotation exhausted.\")\n\n\ndef _post_json(client: httpx.Client, path: str, body: dict, key_pool: KeyPool) -> dict:\n    return _request_json(client.post, path, key_pool, json=body)\n\n\ndef _get_json(client: httpx.Client, path: str, key_pool: KeyPool) -> dict:\n    return _request_json(client.get, path, key_pool)\n\n\ndef _check_code(payload: dict) -> None:\n    \"\"\"MinerU wraps errors in ``{\"code\": <non-zero>, \"msg\": ...}`` even on\n    HTTP 200, so the business code must be inspected explicitly.\"\"\"","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/parsing/engines/mineru/cloud.py#L260-L296","documentation":"An HTTP status error (non-429, or 429 with rotation already used) from a MinerU API call is converted into a friendly message via _http_error_message — e.g. 401/403 token rejection guidance.","triggerScenarios":"API returns 401/403 (bad token), 404 (wrong api_base_url), 5xx, or a second 429 after the key was already rotated once.","commonSituations":"Expired/typo'd API token, wrong base URL, quota exceeded, MinerU outage.","solutions":["Follow the message: for 401/403 re-enter the token in Settings → MinerU.","Verify api_base_url and endpoint version.","Wait and retry for 5xx/429; rotate additional keys if rate-limited often.","Check MinerU status page for outages."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"def token_plausible(k: str) -> bool:\n    return bool(k) and len(k) >= 16","typeGuard":null,"tryCatchPattern":"try:\n    verify_credentials(cfg)\nexcept MinerUError as e:\n    if \"401/403\" in str(e):\n        prompt_reenter_token()\n    else:\n        schedule_retry()","preventionTips":["Run verify_credentials right after entering a token.","Confirm api_base_url matches the official v4 endpoint.","Add extra keys so 429s rotate instead of failing."],"tags":["mineru","cloud","http-status","api-key"],"backgroundTag":"api-http-error","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}