Tencent/WeKnora · error
attachment has no file extension
Error message
attachment has no file extension
What it means
Every IM attachment must carry a file extension, which is used to set attachment FileType and select the document/image parser. If the resolved file name (from the downloader or msg.FileName) has no extension, processing aborts with this error.
Source
Thrown at internal/im/service.go:638
return nil, nil, nil, err
}
defer reader.Close()
content, err := io.ReadAll(io.LimitReader(reader, maxIMAttachmentBytes+1))
if err != nil {
return nil, nil, nil, err
}
if len(content) > maxIMAttachmentBytes {
return nil, nil, nil, fmt.Errorf("attachment exceeds the %d MiB limit", maxIMAttachmentBytes>>20)
}
if fileName == "" {
fileName = msg.FileName
}
if msg.MessageType == MessageTypeImage && filepath.Ext(fileName) == "" {
fileName += ".png"
}
ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(fileName), "."))
if ext == "" {
return nil, nil, nil, fmt.Errorf("attachment has no file extension")
}
attachment := types.MessageAttachment{FileName: fileName, FileType: "." + ext, FileSize: int64(len(content))}
request := &types.ReadRequest{FileContent: content, FileName: fileName, FileType: ext}
var result *types.ReadResult
isImage := msg.MessageType == MessageTypeImage || docparser.IsImageFormat(ext)
if isImage && s.documentReader != nil {
result, err = s.documentReader.Read(attachmentCtx, request)
if err != nil {
logger.Warnf(ctx, "[IM] image OCR/document parsing failed, continuing with vision input: %v", err)
result, err = nil, nil
}
}
if result == nil && docparser.IsSimpleFormat(attachment.FileType) {
result, err = (&docparser.SimpleFormatReader{}).Read(attachmentCtx, request)
} else if result == nil && !isImage && s.documentReader != nil {
result, err = s.documentReader.Read(attachmentCtx, request)
}
if err != nil {View on GitHub (pinned to 988cbb0330)
Solutions
- Rename the file to include an extension before sending
- Ensure your adapter's DownloadFile returns a fileName with an extension (derive from Content-Type/MIME if needed)
- Set msg.FileName to a name with an extension in your adapter/webhook layer
Example fix
// before return reader, "download", nil // no extension // after return reader, "download.pdf", nil // extension derived from Content-Type
Defensive patterns
Strategy: validation
Validate before calling
if msg.MessageType == im.MessageTypeFile && filepath.Ext(msg.FileName) == "" {
return errors.New("file must have an extension")
} Type guard
func hasExtension(name string) bool { return filepath.Ext(name) != "" } Prevention
- Instruct users to send files with proper extensions
- In custom adapters, derive a fileName extension from Content-Type/MIME when the platform omits it
When it happens
Trigger: A file or image message whose fileName (from DownloadFile or msg.FileName) has an empty extension after normalization. Images get a fallback ".png" only when msg.MessageType is image; non-image files with no extension fail.
Common situations: Users uploading extension-less files (common on macOS/Linux); platforms sending sanitized or stripped file names; downloads where the server supplies a generic name with no extension.
Related errors
- a message can use at most %d attachments
- attachment exceeds the %d MiB limit
- invite code has expired
- join request not found
- failed to retrieve: %s
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/69fb53b1bf2aa03d.
Report an issue: GitHub.