{"record":{"id":"bfce896af2797362","repo":"HKUDS/DeepTutor","slug":"no-api-token-configured","errorCode":null,"errorMessage":"No API token configured.","messagePattern":"No API token configured\\.","errorType":"exception","errorClass":"MinerUError","httpStatus":null,"severity":"warning","filePath":"deeptutor/services/parsing/engines/mineru/cloud.py","lineNumber":215,"sourceCode":"            if state == _TERMINAL_FAIL:\n                err = str(entry.get(\"err_msg\") or \"unknown error\")\n                raise MinerUError(f\"MinerU failed to parse the document: {err}\")\n        if time.monotonic() >= deadline:\n            raise MinerUError(\n                f\"MinerU parsing timed out after {int(timeout)}s \"\n                f\"(last state: {last_state or 'unknown'}).\"\n            )\n        time.sleep(poll_interval)\n\n\ndef verify_credentials(config: MinerUConfig) -> None:\n    \"\"\"Best-effort connectivity / token check for the Settings → MinerU \"Test\"\n    button. Requests an upload slot (which does not consume parsing quota and\n    is never followed by an upload, so it simply expires) and validates the\n    business code. Raises :class:`MinerUError` with a user-facing message on\n    any failure.\"\"\"\n    if not config.api_keys:\n        raise MinerUError(\"No API token configured.\")\n    base_url = config.api_base_url.rstrip(\"/\")\n    key_pool = KeyPool(config.api_keys)\n    body: dict[str, object] = {\n        \"files\": [{\"name\": \"connectivity-check.pdf\", \"is_ocr\": False}],\n        \"model_version\": config.model_version,\n        \"enable_formula\": config.enable_formula,\n        \"enable_table\": config.enable_table,\n    }\n    if config.api_language:\n        body[\"language\"] = config.api_language\n    with httpx.Client(base_url=base_url, headers={\"Accept\": \"application/json\"}) as client:\n        _post_json(client, \"/api/v4/file-urls/batch\", body, key_pool)\n\n\ndef _download(zip_url: str) -> bytes:\n    try:\n        response = httpx.get(zip_url, timeout=_DOWNLOAD_TIMEOUT_SECONDS, follow_redirects=True)\n        response.raise_for_status()","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/parsing/engines/mineru/cloud.py#L197-L233","documentation":"The Settings → MinerU 'Test' button (verify_credentials) refuses to run when config.api_keys is empty.","triggerScenarios":"Clicking Test with cloud mode configured but no token saved.","commonSituations":"User selects cloud mode before entering a token, or settings file failed to save.","solutions":["Enter an API token in Settings → MinerU, then Test again.","Verify the settings JSON (data/user/settings) actually persisted the key."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if not cfg.api_keys:\n    return \"Add a token in Settings → MinerU before testing.\"","typeGuard":null,"tryCatchPattern":"try:\n    verify_credentials(cfg)\nexcept MinerUError as e:\n    show_settings_error(str(e))","preventionTips":["Disable the Test button until a token is saved.","Validate token presence at settings-save time."],"tags":["mineru","cloud","api-key","validation"],"backgroundTag":"missing-api-key","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}