{"record":{"id":"c3871d4b681e2142","repo":"instructure/canvas-lms","slug":"localtextextractor-unsupported-mime-type-attachment-mimetype","errorCode":null,"errorMessage":"[LocalTextExtractor] Unsupported MIME type: #{attachment.mimetype}","messagePattern":"\\[LocalTextExtractor\\] Unsupported MIME type: #(.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"app/services/file_text_extraction_service.rb","lineNumber":46,"sourceCode":"  Result = Struct.new(:text, :contains_images)\n\n  def initialize(attachment:)\n    @attachment = attachment\n  end\n\n  def call\n    memory_limit = Setting.get(\"attachment_calculate_words_memory_limit\", 4.gigabytes.to_s).to_i\n    time_limit = Setting.get(\"attachment_calculate_words_time_limit\", 3.minutes.to_s).to_f\n\n    MemoryLimit.apply(memory_limit) do\n      Timeout.timeout(time_limit) do\n        case mimetype\n        when \"pdf\"\n          extract_pdf\n        when \"docx\"\n          extract_docx\n        else\n          Rails.logger.warn(\"[LocalTextExtractor] Unsupported MIME type: #{attachment.mimetype}\")\n          Result.new(\"\", false)\n        end\n      end\n    end\n  rescue => e\n    Rails.logger.error(\"[LocalTextExtractor] Failed for attachment #{attachment.id}: #{e.message}\")\n    Result.new(\"\", false)\n  end\n\n  private\n\n  attr_reader :attachment\n\n  def mimetype\n    return \"pdf\" if attachment.mimetype == \"application/pdf\"\n\n    \"docx\" if %w[\n      application/vnd.openxmlformats-officedocument.wordprocessingml.document","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/services/file_text_extraction_service.rb#L28-L64","documentation":"FileTextExtractionService's local text extractor only handles 'pdf' and 'docx' MIME types; for any other mimetype it logs '[LocalTextExtractor] Unsupported MIME type' and returns Result.new(\"\", false) — an empty, failed extraction, not an exception. It signals that the local extraction path cannot process the attachment's file type.","triggerScenarios":"Calling the service's #call with an attachment whose mimetype is anything other than pdf or docx (e.g. txt, pptx, xlsx, images, odp), causing the case statement to fall into the else branch.","commonSituations":"Users upload unsupported file types (plain text, spreadsheets, images) to a context that expects extracted text; mimetypes stored inconsistently (e.g. 'application/pdf' vs 'pdf') causing the case match to miss; feature routes all attachments through the local extractor instead of a remote extraction service.","solutions":["Check attachment.mimetype before invoking the extractor and skip/route unsupported types to an appropriate extraction backend.","Normalize the mimetype (strip 'application/' prefix, lowercase) if stored values don't match the 'pdf'/'docx' literals expected by the case statement.","Handle the returned Result (success=false, empty text) gracefully rather than assuming extracted text exists.","Extend the case statement to support additional types if those uploads must be indexed, or configure a remote extractor for them."],"exampleFix":"// before\ncase mimetype\nwhen \"pdf\" then extract_pdf\nwhen \"docx\" then extract_docx\nelse\n  Rails.logger.warn(\"[LocalTextExtractor] Unsupported MIME type: #{attachment.mimetype}\")\n  Result.new(\"\", false)\nend\n\n// after: normalize mimetype and pre-validate\ntype = attachment.mimetype.to_s.split(\"/\").last.downcase\ncase type\nwhen \"pdf\" then extract_pdf\nwhen \"vnd.openxmlformats-officedocument.wordprocessingml.document\", \"docx\" then extract_docx\nelse\n  Rails.logger.warn(\"[LocalTextExtractor] Unsupported MIME type: #{attachment.mimetype}\")\n  Result.new(\"\", false)\nend","handlingStrategy":"fallback","validationCode":"// before invoking extraction\nSUPPORTED = %w[pdf docx].freeze\ntype = attachment.mimetype.to_s.split('/').last.downcase\nunless SUPPORTED.include?(type)\n  Rails.logger.info(\"Skipping local extraction for attachment #{attachment.id}: #{attachment.mimetype}\")\n  return\nend","typeGuard":"def extractable?(attachment)\n  %w[pdf docx].include?(attachment.mimetype.to_s.split('/').last.downcase)\nend","tryCatchPattern":"result = FileTextExtractionService.new(attachment: attachment).call\nif result.success\n  use(result.text)\nelse\n  Rails.logger.info(\"No text extracted for attachment #{attachment.id}; falling back to remote extractor\")\nend","preventionTips":["Whitelist allowed upload mimetypes at ingest time so extractors only see supported types.","Check the Result flag (success) instead of assuming text is non-empty.","Normalize mimetypes (lowercase, strip 'application/') before comparison.","Route unsupported types to a remote extraction service instead of the local extractor."],"tags":["file-extraction","mime-type","unsupported-format","fallback"],"backgroundTag":"unsupported-enum-value","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}