clerk / clerk-sdk-ruby

Access the Clerk Backend API from Ruby
MIT License
18 stars 8 forks source link

The message contents of Clerk:Errors is a serialized Ruby object as a string #42

Open yoeun opened 6 months ago

yoeun commented 6 months ago

I ran into this issue trying to match the error code form_identifier_exists in my Clerk::Errors::Fatal handler.

begin
  clerk_sdk.users.create(....)
rescue Clerk::Errors::Fatal => e
  e.errors                # NoMethodError for 'errors'
  e.message               # returns a what looks like Ruby hash object (but actually a string)
  e.message['error']      # NoMethodError for '[]'
end

I think the culprit is this line:

https://github.com/clerk/clerk-sdk-ruby/blob/25c2c18b57611dd79bfc9c03733fb2519ebaaab6/lib/clerk/sdk.rb#L100

It takes the JSON response of the HTTP API and parses it into a ruby object. Then it passes this object into Errors::Fatal.new().

https://github.com/clerk/clerk-sdk-ruby/blob/25c2c18b57611dd79bfc9c03733fb2519ebaaab6/lib/clerk/sdk.rb#L114

The end result is that the error object now has a message that looks like this:

{\"errors\"=>[{\"message\"=>\"That email address is taken. Please try another.\", \"long_message\"=>\"That email address is taken. Please try another.\", \"code\"=>\"form_identifier_exists\", \"meta\"=>{\"param_name\"=>\"email_address\"}}], \"clerk_trace_id\"=>\"...\", \"status\"=>422}

So it's not a ruby object or a JSON string, but a string representation of a ruby object.

There are ways to get around this by using eval() or replacing => with : and parsing as JSON, but I expected the JSON from the HTTP API to be mapped to properties in the Clerk::Errors::Fatal object.

rescue Clerk::Errors::Fatal => e
  # option 1: save JSON parsed HTTP error to `errors` property so I can inspect it myself
  e.errors[0].code

  # option 2: flatten HTTP response to single error
  e.code
end