arsduo/koala · error · Koala::KoalaError

Unable to determine MIME type for UploadableIO

Error message

Unable to determine MIME type for UploadableIO

What it means

UploadableIO raises Koala::KoalaError ('Unable to determine MIME type for UploadableIO') when @content_type is still nil after parsing (lib/koala/http_service/uploadable_io.rb:18). The content type comes from the explicit second constructor argument, else from the mime-types gem if installed (use_mime_module), else from a small built-in extension table (jpg/jpeg, png, gif, plus a list of video extensions). IO objects such as StringIO get no sniffing at all — parse_io only accepts an explicitly passed content_type.

Source

Thrown at lib/koala/http_service/uploadable_io.rb:18

require "tempfile"

module Koala
  module HTTPService
    class UploadableIO
      attr_reader :io_or_path, :content_type, :filename

      def initialize(io_or_path_or_mixed, content_type = nil, filename = nil)
        # see if we got the right inputs
        parse_init_mixed_param io_or_path_or_mixed, content_type

        # filename is used in the Ads API
        # if it's provided, take precedence over the detected filename
        # otherwise, fall back to a dummy name
        @filename = filename || @filename || "koala-io-file.dum"

        raise KoalaError.new("Invalid arguments to initialize an UploadableIO") unless @io_or_path
        raise KoalaError.new("Unable to determine MIME type for UploadableIO") if !@content_type
      end

      def to_upload_io
        UploadIO.new(@io_or_path, @content_type, @filename)
      end

      def to_file
        @io_or_path.is_a?(String) ? File.open(@io_or_path) : @io_or_path
      end

      def self.binary_content?(content)
        content.is_a?(UploadableIO) || DETECTION_STRATEGIES.detect {|method| send(method, content)}
      end

      private
      DETECTION_STRATEGIES = [
        :sinatra_param?,
        :rails_3_param?,

View on GitHub (pinned to 47d052063e)

Solutions

  1. Pass the content type explicitly as the second argument: api.put_picture(io, 'image/png') — the documented form is put_picture(file, content_type, args, target_id)
  2. Use a source with a recognized extension (.jpg/.png/.gif, or common video extensions) so the fallback table resolves
  3. Add the mime-types gem to the Gemfile — Koala's detection strategy uses it for any extension
  4. Preserve extensions when materializing temp files (write to 'upload.jpg', not a random name)

Example fix

# before
api.put_picture(StringIO.new(png_bytes)) # => KoalaError: Unable to determine MIME type for UploadableIO

# after
api.put_picture(StringIO.new(png_bytes), 'image/png')
# or rely on a recognized extension:
api.put_picture('/tmp/avatar.jpg', {message: 'new profile pic'})
Defensive patterns

Strategy: validation

Validate before calling

def media_content_type(source, fallback = 'application/octet-stream')
  return source.content_type if source.respond_to?(:content_type) # Rails uploaded file
  return fallback if source.respond_to?(:read)                   # IO objects cannot be sniffed — be explicit
  ext = File.extname(source).downcase.sub('.', '')
  {'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif',
   'mp4' => 'video/mp4', 'mov' => 'video/quicktime'}.fetch(ext, fallback)
end

api.put_picture(file, media_content_type(file))

Try / catch

begin
  api.put_picture(media, explicit_type)
rescue Koala::KoalaError => e
  # local failure: type undetectable — fall back to an explicit default instead of retrying blind
  api.put_picture(media, 'application/octet-stream')
end

Prevention

When it happens

Trigger: api.put_picture(StringIO.new(data)) with no content_type argument; a file path with a missing or unrecognized extension (/tmp/xyz123, photo.tiff, photo.webp) when the mime-types gem is not installed; an uploaded param whose :type value is blank.

Common situations: Rails Tempfiles whose random paths have no extension; newer formats (.heic, .webp) outside the built-in table; apps that never added the optional mime-types gem; StringIO sources built from downloaded bytes or generated images.

Related errors


AI-assisted analysis of arsduo/koala@47d052063e (2026-08-23). Data as JSON: /api/errors/392a8759efe71632. Report an issue: GitHub.