Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stripe::InvalidRequestError when trying to create Stripe File #761

Closed
AlexanderFisenko opened this issue Apr 12, 2019 · 12 comments · Fixed by #766
Closed

Stripe::InvalidRequestError when trying to create Stripe File #761

AlexanderFisenko opened this issue Apr 12, 2019 · 12 comments · Fixed by #766

Comments

@AlexanderFisenko
Copy link

stripe_file = Stripe::File.create(
  purpose: 'identity_document',
  file: open(self.attachments.last.file.url)
)
self.update_column(:stripe_id, stripe_file.id)

Output:

Exception: Stripe::InvalidRequestError: (Status 400) (Request req_WUYm5h0NwJBBv0) Invalid hash
0: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/stripe-4.12.0/lib/stripe/stripe_client.rb:343:in `handle_error_response'
 1: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/stripe-4.12.0/lib/stripe/stripe_client.rb:294:in `rescue in execute_request_with_rescues'
 2: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/stripe-4.12.0/lib/stripe/stripe_client.rb:257:in `execute_request_with_rescues'
 3: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/stripe-4.12.0/lib/stripe/stripe_client.rb:177:in `execute_request'
 4: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/stripe-4.12.0/lib/stripe/api_operations/request.rb:19:in `request'
 5: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/stripe-4.12.0/lib/stripe/api_operations/create.rb:7:in `create'
 6: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/stripe-4.12.0/lib/stripe/file.rb:31:in `create'
 7: (pry):5:in `upload_to_stripe'
 8: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:387:in `eval'
 9: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:387:in `evaluate_ruby'
10: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:355:in `handle_line'
11: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:274:in `block (2 levels) in eval'
12: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:273:in `catch'
13: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:273:in `block in eval'
14: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:272:in `catch'
15: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:272:in `eval'
16: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib/pry/repl.rb:77:in `block in repl'
17: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib/pry/repl.rb:67:in `loop'
18: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib/pry/repl.rb:67:in `repl'
19: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib/pry/repl.rb:38:in `block in start'
20: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib/pry/input_lock.rb:59:in `__with_ownership'
21: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib/pry/input_lock.rb:77:in `with_ownership'
22: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib/pry/repl.rb:38:in `start'
23: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib/pry/repl.rb:13:in `start'
24: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-0.12.2/lib/pry/pry_class.rb:200:in `start'
25: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-byebug-3.7.0/lib/byebug/processors/pry_processor.rb:117:in `block in resume_pry'
26: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-byebug-3.7.0/lib/byebug/processors/pry_processor.rb:30:in `block (2 levels) in run'
27: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/byebug-11.0.0/lib/byebug/helpers/eval.rb:94:in `allowing_other_threads'
28: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-byebug-3.7.0/lib/byebug/processors/pry_processor.rb:30:in `block in run'
29: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/pry-byebug-3.7.0/lib/byebug/processors/pry_processor.rb:29:in `catch'
Caused by: Faraday::ClientError: the server responded with status 400


0: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/faraday-0.15.4/lib/faraday/response/raise_error.rb:13:in `on_complete'
 1: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/faraday-0.15.4/lib/faraday/response.rb:9:in `block in call'
 2: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/faraday-0.15.4/lib/faraday/response.rb:61:in `on_complete'
 3: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/faraday-0.15.4/lib/faraday/response.rb:8:in `call'
 4: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/faraday-0.15.4/lib/faraday/request/url_encoded.rb:15:in `call'
 5: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/faraday-0.15.4/lib/faraday/request/multipart.rb:15:in `call'
 6: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/faraday-0.15.4/lib/faraday/rack_builder.rb:143:in `build_response'
 7: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/faraday-0.15.4/lib/faraday/connection.rb:387:in `run_request'
 8: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/stripe-4.12.0/lib/stripe/stripe_client.rb:178:in `block in execute_request'
 9: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/stripe-4.12.0/lib/stripe/stripe_client.rb:260:in `execute_request_with_rescues'
10: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/stripe-4.12.0/lib/stripe/stripe_client.rb:177:in `execute_request'
11: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/stripe-4.12.0/lib/stripe/api_operations/request.rb:19:in `request'
12: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/stripe-4.12.0/lib/stripe/api_operations/create.rb:7:in `create'
13: /Users/hammer/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/stripe-4.12.0/lib/stripe/file.rb:31:in `create'
14: (pry):5:in `upload_to_stripe'

Ruby version: 2.6.1
Rails version: 5.2.2
Stripe version: 4.9

@ob-stripe
Copy link
Contributor

@AlexanderFisenko I'm assuming you have a require "open-uri" statement before the call to Stripe::File.create, is that correct?

@AlexanderFisenko
Copy link
Author

@ob-stripe yes

@ob-stripe
Copy link
Contributor

@AlexanderFisenko Okay. Can you double-check that self.attachments.last.file.url is a valid, accessible URL?

@AlexanderFisenko
Copy link
Author

@ob-stripe done. It is.

@ob-stripe
Copy link
Contributor

🤔 Okay. Unfortunately I have no easy way of checking what's happening server-side (since many files contain sensitive information, we do not log the bodies of file creation requests).

Is this an actual identity document file, or a placeholder? If it's just a test file with no sensitive information, mind sharing the URL here so I can try to reproduce the issue?

@AlexanderFisenko
Copy link
Author

@ob-stripe
Copy link
Contributor

ob-stripe commented Apr 15, 2019

Thanks! I was able to reproduce the issue. Looks like the library is not sending the actual file contents in the request:

-------------RubyMultipartPost-d990743726d2962b06031f5614e5ff2e
Content-Disposition: form-data; name="purpose"

identity_document
-------------RubyMultipartPost-d990743726d2962b06031f5614e5ff2e
Content-Disposition: form-data; name="file"

#<StringIO:0x00007f8618889cf8>
-------------RubyMultipartPost-d990743726d2962b06031f5614e5ff2e--

After investigating, it looks like our strategy for detecting File-like objects here (introduced in #616 and basically copied from the rest-client gem) does not support open-uri, because files opened by open-uri do not respond to :path.

@brandur-stripe I think we can relax the check and simply check if the provided object responds to :read. wdyt?

@brandur-stripe
Copy link
Contributor

Nice find @ob-stripe!

I can't think of any reason that we can't just reduce it to read, so that totally works for me.

I'm on run, so I can take if you like it, but feel free to go for it if you were already doing it and I can take review/release.

@ob-stripe
Copy link
Contributor

@brandur-stripe Yep, would be great if you could take it (happy to review). I also wonder if we should throw an explicit error if the file param is not a File-like object and not a String, to avoid simply sending a string representation that will result in this obscure "Invalid hash" server-side error.

brandur-stripe pushed a commit that referenced this issue Apr 16, 2019
When uploading a file, we previously made a check on whether it
supported both `#read` and `#path` before wrapping it in a
`Faraday::UploadIO` and sending it off. The second check on `#path`
isn't strictly necessary, and as reported in #761 can prevent objects
created by `open-uri` from being compatible with file upload.

Here we remove the check `#path` so that we just require that objects
support `#read`, and in addition error when an object is passed that's
not file-compatible and not a string. This should prevent users from
seeing the very confusing "Invalid hash" error in these situations.

Fixes #761.
@brandur-stripe
Copy link
Contributor

@ob-stripe Good call. Took a shot at this in #766.

brandur-stripe pushed a commit that referenced this issue Apr 16, 2019
When uploading a file, we previously made a check on whether it
supported both `#read` and `#path` before wrapping it in a
`Faraday::UploadIO` and sending it off. The second check on `#path`
isn't strictly necessary, and as reported in #761 can prevent objects
created by `open-uri` from being compatible with file upload.

Here we remove the check `#path` so that we just require that objects
support `#read`, and in addition error when an object is passed that's
not file-compatible and not a string. This should prevent users from
seeing the very confusing "Invalid hash" error in these situations.

Fixes #761.
@brandur-stripe
Copy link
Contributor

4.13.0 should contain the fix you need.

(And thanks Olivier for diagnosing the problem!)

@AlexanderFisenko
Copy link
Author

@brandur-stripe @oliver-stripe thanks guys!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants