ruby-grape/grape · error · ArgumentError
Argument must be a file path
Error message
Argument must be a file path
What it means
`sendfile` hands a file to the client via Grape::ServeStream::FileBody, which needs a filesystem path it can open lazily. The guard requires the argument to be a String; File handles, Pathname objects, or any IO-like object raise 'Argument must be a file path'. Note this is stricter than Rack, which also accepts objects responding to to_path.
Source
Thrown at lib/grape/dsl/inside_route.rb:125
# end
#
# DELETE /12 # => 204 No Content, ""
def return_no_content
body false
end
# Allows you to send a file to the client via sendfile.
#
# @example
# get '/file' do
# sendfile FileStreamer.new(...)
# end
#
# GET /file # => "contents of file"
def sendfile(value = nil)
return stream if value.nil?
raise ArgumentError, 'Argument must be a file path' unless value.is_a?(String)
file_body = Grape::ServeStream::FileBody.new(value)
@stream = Grape::ServeStream::StreamResponse.new(file_body)
end
# Allows you to define the response as a streamable object.
#
# If Content-Length and Transfer-Encoding are blank (among other conditions),
# Rack assumes this response can be streamed in chunks.
#
# @example
# get '/stream' do
# stream FileStreamer.new(...)
# end
#
# GET /stream # => "chunked contents of file"
#
# See:View on GitHub (pinned to 22d7975629)
Solutions
- Pass the path string: `sendfile file.path` for File/Tempfile, `sendfile pathname.to_s` for Pathname.
- If you have an IO object rather than a path, use the `stream` helper with an each-responding wrapper instead of `sendfile`.
Example fix
# before
sendfile Pathname.new('/files/report.pdf') # raises
sendfile uploaded_tempfile # Tempfile object raises
# after
sendfile Pathname.new('/files/report.pdf').to_s
sendfile uploaded_tempfile.path Defensive patterns
Strategy: type-guard
Validate before calling
path = case value
when String then value
when File, Tempfile then value.path
when Pathname then value.to_s
else raise ArgumentError, "cannot derive a file path from #{value.class}"
end
sendfile path Type guard
def sendfile_path?(value) = value.is_a?(String) && !value.empty?
Prevention
- Standardize on `sendfile obj.path` / `sendfile obj.to_s` everywhere in the codebase.
- Use the `stream` helper for IO objects that have no path.
- Add a spec for the file-serving endpoint in CI so argument-type regressions surface early.
When it happens
Trigger: `sendfile File.open('/tmp/x.csv')` (File object). `sendfile Pathname.new('/tmp/x.csv')` (Pathname). `sendfile tempfile` where tempfile is a Tempfile from a multipart upload instead of `tempfile.path`.
Common situations: Streaming generated reports or uploads stored on disk. Reusing Rack/Sinatra send_file idioms that accept Pathname or File. Passing the result of another API that returns a file handle.
Related errors
- Status code must be Integer or Symbol.
- with: #{with.class}, expected Symbol, String or Proc
- type #{type} should support coercion via `[]`
- #declared is not available prior to parameter validation
- Representation of type #{representation.class} cannot be mer
AI-assisted analysis of ruby-grape/grape@22d7975629 (2026-08-21).
Data as JSON: /api/errors/cf9a771da0edf940.
Report an issue: GitHub.