{"record":{"id":"3274674f6daf1279","repo":"chatboxai/chatbox","slug":"mineru-api-token-required","errorCode":null,"errorMessage":"mineru_api_token_required","messagePattern":"mineru_api_token_required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/renderer/stores/sessionHelpers.ts","lineNumber":657,"sourceCode":"      switch (parserConfig.type) {\n        case 'none': {\n          throw new Error('document_parser_not_configured')\n        }\n\n        case 'local': {\n          result = await parseFileWithLocalFallback(file, uniqKey)\n          break\n        }\n\n        case 'chatbox-ai': {\n          result = await parseFileWithLocalFallback(file, uniqKey, { forceChatboxAIFallback: true })\n          break\n        }\n\n        case 'mineru': {\n          const apiToken = parserConfig.mineru?.apiToken\n          if (!apiToken) {\n            throw new Error('mineru_api_token_required')\n          }\n          try {\n            result = await parseFileWithMineruService(file, uniqKey, apiToken)\n          } catch (error) {\n            log.error(`MinerU parsing failed for \"${file.name}\":`, error)\n            if (\n              error instanceof Error &&\n              (error.message === EMPTY_ATTACHMENT_CONTENT_ERROR || error.message.startsWith('third_party_parser'))\n            ) {\n              throw error\n            }\n            throw new Error('third_party_parser_failed')\n          }\n          break\n        }\n\n        default: {\n          throw new Error('document_parser_not_configured')","sourceCodeStart":639,"sourceCodeEnd":675,"githubUrl":"https://github.com/chatboxai/chatbox/blob/81571269addb6bafb589a920b2883f1e1e084fd1/src/renderer/stores/sessionHelpers.ts#L639-L675","documentation":"Thrown in the 'mineru' case of the parser switch when parserConfig.mineru?.apiToken is falsy. The MinerU parser type was selected but no API token is configured, so the call cannot proceed. It is thrown before parseFileWithMineruService is invoked, so no network call is attempted.","triggerScenarios":"getEffectiveDocumentParserConfig() returns { type:'mineru', mineru: { apiToken: undefined | '' } }. The destructured apiToken is falsy and the guard throws immediately.","commonSituations":"User selected MinerU in the parser dropdown but never entered an API token; token was cleared by a settings reset; token stored under a different key than parserConfig.mineru.apiToken after a config-schema migration; user pasted only whitespace.","solutions":["Open Settings → Document Parser → MinerU and paste a valid MinerU API token (obtain one from the MinerU dashboard), then re-attach the file.","Validate the token field is non-empty before allowing the 'mineru' option to be saved — surface a field error in the UI rather than throwing at parse time.","If you cannot obtain a MinerU token, switch the parser to 'local' or 'chatbox-ai' which do not require one.","After a config migration, run a repair step that re-maps any stale token field name to parserConfig.mineru.apiToken."],"exampleFix":"// before\nconst apiToken = parserConfig.mineru?.apiToken\nif (!apiToken) {\n  throw new Error('mineru_api_token_required')\n}\n// after — trim and give a clearer, actionable error\nconst apiToken = parserConfig.mineru?.apiToken?.trim()\nif (!apiToken) {\n  throw new Error('mineru_api_token_required: set it in Settings → Document Parser → MinerU')\n}","handlingStrategy":"validation","validationCode":"// Validate the MinerU token before allowing the parser to be saved/used.\nfunction mineruTokenIsSet(cfg: DocumentParserConfig): boolean {\n  return Boolean(cfg.mineru?.apiToken && cfg.mineru.apiToken.trim().length > 0)\n}\nif (cfg.type === 'mineru' && !mineruTokenIsSet(cfg)) {\n  // block save or surface a field error\n}","typeGuard":"function hasMineruToken(cfg: unknown): cfg is { type:'mineru'; mineru: { apiToken: string } } {\n  return typeof cfg === 'object' && cfg !== null &&\n    (cfg as any).type === 'mineru' &&\n    typeof (cfg as any).mineru?.apiToken === 'string' &&\n    (cfg as any).mineru.apiToken.trim().length > 0\n}","tryCatchPattern":"try {\n  await preprocessFile(file)\n} catch (e) {\n  if (e instanceof Error && e.message === 'mineru_api_token_required') {\n    openSettings('documentParser.mineru.apiToken')\n    return\n  }\n  throw e\n}","preventionTips":["Make the MinerU token field required (UI validation) when type === 'mineru'.","Trim whitespace on save; reject empty/whitespace tokens at the settings layer.","Run a config-repair pass on version upgrades to remap any renamed token field to mineru.apiToken."],"tags":["mineru","config","missing-secret","user-action-required"],"backgroundTag":null,"analyzedSha":"81571269addb6bafb589a920b2883f1e1e084fd1","analyzedAt":"2026-08-12T21:51:44.981Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}