OtterMind/Chat2DB · error · BusinessException
ai.attachment.unsupportedFileType
ai.attachment.unsupportedFileType
Error message
ai.attachment.unsupportedFileType
What it means
Thrown by the `default` arm of the extension switch in AiAttachmentServiceImpl.parse(String, InputStream). It is a defensive safety-net: validateExtension() runs immediately before the switch and already rejects any extension outside the supported set, so under normal control flow this branch is unreachable. The i18n message resolves to 'This file type is not supported'.
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:150
}
public boolean hasAttachment(List<ChatAttachment> attachments) {
return attachments != null && attachments.stream()
.anyMatch(item -> item != null && StringUtils.isNotBlank(item.getContent()));
}
private ChatAttachment parse(String fileName, InputStream inputStream) throws IOException {
String extension = StringUtils.lowerCase(FilenameUtils.getExtension(fileName));
validateExtension(extension);
String content = switch (extension) {
case "pdf" -> parsePdf(inputStream);
case "docx" -> parseDocx(inputStream);
case "doc" -> parseDoc(inputStream);
case "csv" -> parseCsv(inputStream);
case "xls", "xlsx" -> parseWorkbook(inputStream);
case "md", "txt", "json" -> readPlainText(inputStream);
default -> throw new BusinessException("ai.attachment.unsupportedFileType");
};
String normalizedContent = normalizeText(content);
if (StringUtils.isBlank(normalizedContent)) {
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;View on GitHub (pinned to 5ee1e990e7)
Solutions
- If you hit this in production, check whether SUPPORTED_EXTENSIONS was extended without a matching switch case, and add the parser.
- If you are a maintainer, keep SUPPORTED_EXTENSIONS and the switch in sync, or derive the switch source-of-truth from a single map of extension->parser.
- Callers cannot legitimately hit this; treat it as an internal bug and report the extension value in the exception args.
Example fix
// before: extension added to supported set but no case
private static final Set<String> DOCUMENT_EXTENSIONS =
Set.of("pdf","doc","docx","md","txt","json","html"); // html passes validateExtension
// switch has no case "html" -> falls to default
// after: add the parser case, or reject in validateExtension
private static final Set<String> DOCUMENT_EXTENSIONS =
Set.of("pdf","doc","docx","md","txt","json");
// and in the switch:
case "html" -> parseHtml(inputStream); Defensive patterns
Strategy: validation
Validate before calling
// This branch is normally unreachable; if reached it is an internal bug.
// Validate extension against the same set the switch covers before delegating.
String ext = StringUtils.lowerCase(FilenameUtils.getExtension(fileName));
if (!Set.of("pdf","doc","docx","csv","xls","xlsx","md","txt","json").contains(ext)) {
return ResponseEntity.badRequest().body("unsupported type: " + ext);
} Prevention
- Keep SUPPORTED_EXTENSIONS and the parse switch in sync when adding types.
- Treat this error as a defect report; capture the extension value for debugging.
- Add a unit test asserting every SUPPORTED_EXTENSIONS entry has a switch case.
When it happens
Trigger: Only reachable if validateExtension is bypassed or if SUPPORTED_EXTENSIONS and the switch cases drift out of sync (e.g. a new extension added to SUPPORTED_EXTENSIONS without a matching parser case). The switch handles pdf, docx, doc, csv, xls, xlsx, md, txt, json - exactly the supported set.
Common situations: A maintainer adds an extension to DOCUMENT_EXTENSIONS/TABULAR_EXTENSIONS (which feeds SUPPORTED_EXTENSIONS) so it passes validateExtension, but forgets to add a `case` to the switch, falling through to default. Regression after refactoring the parse dispatch.
Related errors
- ai.attachment.localParseFailed
- ai.attachment.emptyContent
- ai.attachment.filePathRequired
- ai.attachment.fileNotFound
- ai.attachment.unsupportedFileExtensions
AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14).
Data as JSON: /api/errors/0f12d6d1875b19bc.
Report an issue: GitHub.