{"record":{"id":"c0340358c646b0f9","repo":"HKUDS/DeepTutor","slug":"mineru-cloud-mode-is-selected-but-no-api-token-is","errorCode":null,"errorMessage":"MinerU cloud mode is selected but no API token is configured. Add a token in Settings → MinerU, or switch to local mode.","messagePattern":"MinerU cloud mode is selected but no API token is configured\\. Add a token in Settings → MinerU, or switch to local mode\\.","errorType":"exception","errorClass":"MinerUError","httpStatus":null,"severity":"error","filePath":"deeptutor/services/parsing/engines/mineru/cloud.py","lineNumber":71,"sourceCode":"def parse_cloud(\n    pdf_path: Path,\n    output_base: Path,\n    config: MinerUConfig,\n    *,\n    poll_interval: float = DEFAULT_POLL_INTERVAL_SECONDS,\n    timeout: float = DEFAULT_TIMEOUT_SECONDS,\n    on_progress: Callable[[str], None] | None = None,\n) -> Path:\n    \"\"\"Parse ``pdf_path`` via the MinerU cloud API; return the working dir.\n\n    The working dir sits under ``output_base`` (named after the PDF stem) and\n    holds the unzipped MinerU artifacts. ``on_progress`` (if given) receives a\n    short status line whenever the polled task state / page count changes.\n    Raises :class:`MinerUError` on any misconfiguration, API error, timeout,\n    or extraction failure.\n    \"\"\"\n    if not config.api_keys:\n        raise MinerUError(\n            \"MinerU cloud mode is selected but no API token is configured. \"\n            \"Add a token in Settings → MinerU, or switch to local mode.\"\n        )\n    pdf_path = Path(pdf_path)\n    if not pdf_path.is_file():\n        raise MinerUError(f\"PDF file not found: {pdf_path}\")\n\n    base_url = config.api_base_url.rstrip(\"/\")\n    key_pool = KeyPool(config.api_keys)\n\n    def report(message: str) -> None:\n        if on_progress is None:\n            return\n        try:\n            on_progress(message)\n        except Exception:\n            logger.debug(\"on_progress callback failed\", exc_info=True)\n","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/parsing/engines/mineru/cloud.py#L53-L89","documentation":"Cloud mode was selected but config.api_keys is empty, so parse_cloud refuses before any network call.","triggerScenarios":"Calling parse_pdf_to_workdir (or parse_cloud) with mode=cloud and no API token saved in Settings → MinerU.","commonSituations":"Fresh install without configuring a token, settings JSON reset, or a test env lacking credentials.","solutions":["Add a MinerU API token in Settings → MinerU.","Or switch mode to local (requires mineru installed).","In code, assert config.api_keys before calling."],"exampleFix":"# before\nresult = parse_pdf_to_workdir(pdf, workdir, config)  # mode=cloud, no keys\n\n# after\nif not config.api_keys:\n    raise ValueError(\"configure MinerU API token first\")\nresult = parse_pdf_to_workdir(pdf, workdir, config)","handlingStrategy":"validation","validationCode":"if mode == \"cloud\" and not cfg.api_keys:\n    raise ValueError(\"MinerU cloud token missing — configure it before parsing\")","typeGuard":null,"tryCatchPattern":"try:\n    parse_cloud(...)\nexcept MinerUError as e:\n    if \"no API token\" in str(e):\n        prompt_user_for_token()","preventionTips":["Assert api_keys non-empty before any cloud call.","Persist and verify the token with verify_credentials after saving."],"tags":["mineru","cloud","api-key","configuration"],"backgroundTag":"missing-api-key","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}