OtterMind/Chat2DB · error · BusinessException

ai.attachment.unsupportedFileExtensions

ai.attachment.unsupportedFileExtensions

Error message

ai.attachment.unsupportedFileExtensions

What it means

Thrown by AiAttachmentServiceImpl.validateExtension when the extension is blank or not in SUPPORTED_EXTENSIONS. This is the primary extension gate, invoked at the top of parse(String, InputStream) before the type dispatch. The i18n message resolves to 'Only pdf, doc, docx, md, txt, json, csv, xls, and xlsx files are supported'. Supported = DOCUMENT(pdf,doc,docx,md,txt,json) + TABULAR(csv,xls,xlsx).

Source

Thrown at chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/ai/AiAttachmentServiceImpl.java:173

            throw new BusinessException("ai.attachment.emptyContent");
        }

        boolean truncated = normalizedContent.length() > MAX_CONTENT_LENGTH;
        String finalContent = truncated ? normalizedContent.substring(0, MAX_CONTENT_LENGTH) : normalizedContent;

        ChatAttachment attachment = new ChatAttachment();
        attachment.setFileName(fileName);
        attachment.setFileType(extension);
        attachment.setContentCategory(resolveContentCategory(extension));
        attachment.setContent(finalContent);
        attachment.setContentLength(normalizedContent.length());
        attachment.setTruncated(truncated);
        return attachment;
    }

    private void validateExtension(String extension) {
        if (StringUtils.isBlank(extension) || !SUPPORTED_EXTENSIONS.contains(extension)) {
            throw new BusinessException("ai.attachment.unsupportedFileExtensions");
        }
    }

    private String resolveContentCategory(String extension) {
        return TABULAR_EXTENSIONS.contains(extension) ? "TABULAR" : "DOCUMENT";
    }

    private String parsePdf(InputStream inputStream) throws IOException {
        try (PDDocument document = PDDocument.load(inputStream)) {
            return new PDFTextStripper().getText(document);
        }
    }

    private String parseDocx(InputStream inputStream) throws IOException {
        try (XWPFDocument document = new XWPFDocument(inputStream);
             XWPFWordExtractor extractor = new XWPFWordExtractor(document)) {
            return extractor.getText();
        }

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Restrict the upload accept list in the renderer to the supported extensions and validate before submit.
  2. Convert the file to a supported type (e.g. export .pptx to .pdf, save .rtf as .docx).
  3. If you need a new type, add it to DOCUMENT_EXTENSIONS/TABULAR_EXTENSIONS AND add the matching switch case + parser.

Example fix

// before: uploader accepts all files
<input type="file" />

// after: limit to supported types
<input type="file"
  accept=".pdf,.doc,.docx,.md,.txt,.json,.csv,.xls,.xlsx" />
Defensive patterns

Strategy: validation

Validate before calling

Set<String> OK = Set.of("pdf","doc","docx","md","txt","json","csv","xls","xlsx");
String ext = StringUtils.lowerCase(FilenameUtils.getExtension(fileName));
if (StringUtils.isBlank(ext) || !OK.contains(ext)) {
    return ResponseEntity.badRequest().body("unsupported extension: " + ext);
}

Try / catch

try {
    service.parse(param);
} catch (BusinessException e) {
    if ("ai.attachment.unsupportedFileExtensions".equals(e.getCode())) {
        return ResponseEntity.badRequest().body(e.getMessage());
    }
    throw e;
}

Prevention

When it happens

Trigger: Uploading a file whose extension (case-insensitive) is not in the supported set, e.g. .rtf, .html, .pptx, .png, .eml, or a file with no extension at all. FilenameUtils.getExtension returns '' for dotfiles/no-extension names, which is blank and fails the check.

Common situations: User drags an unsupported format into the AI attachment panel; a file renamed to .pdf but actually another format still passes this gate (it fails later at parsing); a dotfile like '.gitignore' yields a blank extension; case variants like .PDF are fine because the extension is lowercased before the check.

Related errors


AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14). Data as JSON: /api/errors/41075ff0b8b36b26. Report an issue: GitHub.