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
- 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)
- Use a source with a recognized extension (.jpg/.png/.gif, or common video extensions) so the fallback table resolves
- Add the mime-types gem to the Gemfile — Koala's detection strategy uses it for any extension
- 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
- Always pass content_type explicitly when the source is StringIO/IO — there is no filename to sniff
- Add mime-types to the Gemfile so extension detection covers more than the tiny built-in table
- Preserve file extensions when writing Tempfiles (write to 'upload.jpg', not a random name)
- Restrict uploads to formats Facebook handles (jpg, png, gif, mp4, mov, ...) and validate the extension server-side
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
- Invalid arguments to initialize an UploadableIO
- Koala::Facebook::ServerError.new(result.status.to_i, result.
- Batch operations require an access token, none provided.
- Delete requires an access token
- Write operations require an access token
AI-assisted analysis of arsduo/koala@47d052063e (2026-08-23).
Data as JSON: /api/errors/392a8759efe71632.
Report an issue: GitHub.