{"record":{"id":"1f68448275d9e320","repo":"chatboxai/chatbox","slug":"knowledge-base-parsed-content-too-large","errorCode":"knowledge_base_parsed_content_too_large","errorMessage":"knowledge_base_parsed_content_too_large","messagePattern":"knowledge_base_parsed_content_too_large","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/knowledge-base/file-loaders.ts","lineNumber":73,"sourceCode":"// Parse file to MDocument using the parser router\nasync function parseFileToDocumentWithRouter(\n  filePath: string,\n  fileMeta: ParserFileMeta,\n  kbId: number,\n  parserConfig: DocumentParserConfig\n): Promise<{ document: MDocument; parserUsed: string }> {\n  log.info(`[FILE] Parsing ${fileMeta.filename} with ${parserConfig.type} parser`)\n\n  const result = await parseFileWithRouter(filePath, fileMeta, parserConfig, kbId)\n\n  log.info(`[FILE] Parse completed for ${fileMeta.filename}, parser used: ${result.parserUsed}`)\n\n  const parsedContentByteLength = Buffer.byteLength(result.content, 'utf8')\n  if (parsedContentByteLength > KNOWLEDGE_BASE_MAX_PARSED_CONTENT_SIZE) {\n    log.info(\n      `[FILE] Parsed content too large: filename=${fileMeta.filename}, bytes=${parsedContentByteLength}, limit=${KNOWLEDGE_BASE_MAX_PARSED_CONTENT_SIZE}`\n    )\n    throw new Error(KNOWLEDGE_BASE_PARSED_CONTENT_TOO_LARGE_ERROR)\n  }\n\n  // Convert content to MDocument based on content type\n  const document = MDocument.fromText(result.content)\n  return { document, parserUsed: result.parserUsed }\n}\n\n// Use mastra to parse, chunk, embed, and store files\nexport async function processFileWithMastra(\n  filePath: string,\n  fileMeta: { fileId: number; filename: string; mimeType: string },\n  kbId: number,\n  parserConfig: DocumentParserConfig\n) {\n  const startTime = Date.now()\n  log.debug(\n    `[FILE] Starting file processing: ${fileMeta.filename} (id=${fileMeta.fileId}, parser=${parserConfig.type})`\n  )","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/chatboxai/chatbox/blob/81571269addb6bafb589a920b2883f1e1e084fd1/src/main/knowledge-base/file-loaders.ts#L55-L91","documentation":"Thrown by CustomGemini.listModels() when GET `${apiHost}/models?key=...` returns a body without a top-level `models` array. Note: this method is wrapped in try/catch that logs and returns `[]`, so the ApiError itself only escapes if a caller rethrows or if the catch is bypassed — but it is the documented failure signal. The Gemini ListModels API normally returns `{ models: [{ name, displayName, supportedGenerationMethods, ... }] }`, so a missing `models` field means the request did not reach a real Gemini-style models endpoint.","triggerScenarios":"Invalid `apiKey` (Google returns `{ error: { code: 400, message: 'API key not valid...' } }`); `apiHost` points to an OpenAI-compatible relay whose `/models` returns `{ data: [...] }`; the key query param is URL-mangled by a proxy; the custom host does not implement the `/models` route at all (returns `{}` or HTML); quota/billing disabled the key and Google returns an error envelope.","commonSituations":"Custom Gemini provider configured with the OpenAI-style host by mistake; key generated for a different Google project / restricted API; corporate proxy strips the `?key=` query parameter; the host includes `/v1beta` already so the URL becomes `.../v1beta/v1beta/models`; region where Generative Language API is unavailable returns a non-models JSON.","solutions":["Inspect the JSON.stringify'd payload — `{ error: {...} }` from Google means auth/quota/permission issue; `{ data: [...] }` means the host is OpenAI-style and you should switch provider type.","Confirm `apiHost` is the base origin (e.g. `https://generativelanguage.googleapis.com`) without a `/v1beta` suffix; normalizeGeminiHost appends the version.","Verify the API key is enabled for the Generative Language API in the Google Cloud project and has no referring-URL restriction that blocks the request.","If using a relay that only exposes OpenAI `/v1/models`, switch to a Custom OpenAI provider instead of Custom Gemini."],"exampleFix":"// before: relay returns { data: [...] }, throws '{\"data\":[...]}'\n// after: detect schema and adapt, or fall back to manual model list\nif (!json.models && json.data) {\n  return json.data.map((m) => ({ modelId: m.id, type: 'chat' as const }))\n}\nif (!json.models) throw new ApiError(JSON.stringify(json))","handlingStrategy":"try-catch","validationCode":"async function probeCustomGeminiModels(host: string, key: string): Promise<boolean> {\n  const res = await fetch(`${host}/models?key=${encodeURIComponent(key)}`)\n  const json = await res.json().catch(() => ({}))\n  return Array.isArray((json as any)?.models)\n}","typeGuard":"function isGeminiModelsResponse(json: unknown): json is { models: { name: string; supportedGenerationMethods: string[] }[] } {\n  return typeof json === 'object' && json !== null && Array.isArray((json as any).models)\n}","tryCatchPattern":"// listModels already wraps in try/catch returning []; ensure callers handle the empty array\nconst models = await customGemini.listModels()\nif (models.length === 0) showFallbackModelList()","preventionTips":["During custom provider setup, probe the host and reject hosts whose /models returns a non-Gemini schema.","Confirm the Google project enables the Generative Language API and the key is unrestricted.","Use base-origin hosts; let normalizeGeminiHost append /v1beta."],"tags":["api","gemini","custom-provider","models-list","configuration","proxy"],"backgroundTag":null,"analyzedSha":"81571269addb6bafb589a920b2883f1e1e084fd1","analyzedAt":"2026-08-12T21:51:44.981Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}