{"record":{"id":"f82f3ca40996511e","repo":"chatboxai/chatbox","slug":"empty-attachment-content","errorCode":"empty_attachment_content","errorMessage":"empty_attachment_content","messagePattern":"empty_attachment_content","errorType":"exception","errorClass":"FilePreprocessFailure","httpStatus":null,"severity":"warning","filePath":"src/renderer/stores/sessionHelpers.ts","lineNumber":421,"sourceCode":"\nfunction shouldFallbackToChatboxAI(options: LocalParserFallbackOptions): boolean {\n  return (\n    Boolean(options.forceChatboxAIFallback) || (options.allowChatboxAIFallback !== false && canFallbackToChatboxAI())\n  )\n}\n\nasync function parseFileWithLocalFallback(\n  file: File,\n  uniqKey: string,\n  options: LocalParserFallbackOptions = {}\n): Promise<{ content: string; storageKey: string; tokenCountMap: Record<string, number>; parserType: string }> {\n  try {\n    const result = await parseFileWithLocalParser(file, uniqKey)\n    if (!hasParsedText(result.content)) {\n      if (shouldFallbackToChatboxAI(options)) {\n        return await fallbackToChatboxAIParser(file, uniqKey, 'empty_content')\n      }\n      throw new FilePreprocessFailure(\n        EMPTY_ATTACHMENT_CONTENT_ERROR,\n        'local_parse',\n        new Error('Local parser returned empty content')\n      )\n    }\n    return result\n  } catch (error) {\n    log.error(`Local parsing failed for \"${file.name}\":`, error)\n\n    // Already classified (e.g. a storage-quota failure from the empty-content cloud\n    // fallback above) — propagate as-is instead of re-classifying or retrying.\n    if (error instanceof FilePreprocessFailure) {\n      throw error\n    }\n\n    // Encrypted or oversized PDFs cannot be recovered by the cloud parser either,\n    // so surface the specific error directly instead of wasting a fallback upload.\n    const errorCode = error instanceof Error ? error.message : ''","sourceCodeStart":403,"sourceCodeEnd":439,"githubUrl":"https://github.com/chatboxai/chatbox/blob/81571269addb6bafb589a920b2883f1e1e084fd1/src/renderer/stores/sessionHelpers.ts#L403-L439","documentation":"FilePreprocessFailure with code empty_attachment_content, thrown from parseFileWithLocalFallback when the local parser returned no readable text and Chatbox AI fallback is disabled/unavailable. The check uses hasParsedText(result.content); empty or whitespace-only content with no fallback path yields this specific code so the UI can explain that the file has no extractable text.","triggerScenarios":"Local parse succeeded (isSupported true, key present) but the extracted content is empty/blank: scanned PDF without OCR, image-only PDF, empty file, or a binary file the parser read as zero text. shouldFallbackToChatboxAI(options) is false (fallback disabled or canFallbackToChatboxAI() false).","commonSituations":"User attaches a scanned document or image-heavy PDF to a model that lacks OCR, an empty file, or cloud fallback turned off (offline, no license, admin-disabled).","solutions":["Enable Chatbox AI cloud fallback so empty local results retry with the cloud OCR-capable parser.","Inform the user the file has no extractable text and suggest OCR/vision-capable model.","Pre-screen attachments for known empty-content cases (zero-byte, image-only PDFs).","Verify canFallbackToChatboxAI() returns true when a license and connectivity are present."],"exampleFix":"// before\nif (!hasParsedText(result.content)) {\n  if (shouldFallbackToChatboxAI(options)) {\n    return await fallbackToChatboxAIParser(file, uniqKey, 'empty_content')\n  }\n  throw new FilePreprocessFailure(EMPTY_ATTACHMENT_CONTENT_ERROR, 'local_parse', new Error('Local parser returned empty content'))\n}\n// after\nif (!hasParsedText(result.content)) {\n  if (shouldFallbackToChatboxAI(options)) {\n    return await fallbackToChatboxAIParser(file, uniqKey, 'empty_content')\n  }\n  throw new FilePreprocessFailure(EMPTY_ATTACHMENT_CONTENT_ERROR, 'local_parse', new Error('Local parser returned empty content'))\n}","handlingStrategy":"fallback","validationCode":"const result = await parseFileWithLocalParser(file, uniqKey)\nif (!hasParsedText(result.content) && !shouldFallbackToChatboxAI(options)) {\n  // will throw empty_attachment_content; consider enabling fallback\n}","typeGuard":"function isEmptyAttachmentFailure(e: unknown): boolean {\n  return e instanceof Error && (e as { code?: string }).code === 'empty_attachment_content'\n}","tryCatchPattern":"try {\n  return await parseFileWithLocalFallback(file, uniqKey, options)\n} catch (err) {\n  if (isEmptyAttachmentFailure(err)) {\n    notifyUser('This file has no extractable text. Try an OCR-capable model or cloud parser.')\n    return null\n  }\n  throw err\n}","preventionTips":["Enable Chatbox AI cloud fallback so empty local results retry remotely.","Pre-screen image-only PDFs / zero-byte files before parsing.","Ensure canFallbackToChatboxAI() returns true when a license and connectivity exist."],"tags":["file-parsing","empty-content","attachments","ocr","fallback"],"backgroundTag":null,"analyzedSha":"81571269addb6bafb589a920b2883f1e1e084fd1","analyzedAt":"2026-08-12T21:51:44.981Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}