diff --git a/lib/temporal/workflow/errors.rb b/lib/temporal/workflow/errors.rb index d7c294f5..cea7f471 100644 --- a/lib/temporal/workflow/errors.rb +++ b/lib/temporal/workflow/errors.rb @@ -25,7 +25,7 @@ def self.generate_error(failure, default_exception_class = StandardError) begin exception = exception_class.new(message) - rescue ArgumentError => deserialization_error + rescue => deserialization_error # We don't currently support serializing/deserializing exceptions with more than one argument. message = "#{exception_class}: #{message}" exception = default_exception_class.new(message) @@ -33,6 +33,7 @@ def self.generate_error(failure, default_exception_class = StandardError) "Could not instantiate original error. Defaulting to StandardError.", { original_error: failure.application_failure_info.type, + instantiation_error_class: deserialization_error.class.to_s, instantiation_error_message: deserialization_error.message, }, ) diff --git a/spec/unit/lib/temporal/workflow/errors_spec.rb b/spec/unit/lib/temporal/workflow/errors_spec.rb index a9e053f6..05d5f82a 100644 --- a/spec/unit/lib/temporal/workflow/errors_spec.rb +++ b/spec/unit/lib/temporal/workflow/errors_spec.rb @@ -4,6 +4,15 @@ class ErrorWithTwoArgs < StandardError def initialize(message, another_argument); end end +class ErrorThatRaisesInInitialize < StandardError + def initialize(message) + # This class simulates an error class that has bugs in its initialize method, or where + # the arg isn't a string. It raises the sort of TypeError that would happen if you wrote + # 1 + message + raise TypeError.new("String can't be coerced into Integer") + end +end + class SomeError < StandardError; end describe Temporal::Workflow::Errors do @@ -51,7 +60,7 @@ class SomeError < StandardError; end end - it "falls back to StandardError when the client can't initialize the error class" do + it "falls back to StandardError when the client can't initialize the error class due to arity" do allow(Temporal.logger).to receive(:error) message = "An error message" @@ -73,10 +82,38 @@ class SomeError < StandardError; end 'Could not instantiate original error. Defaulting to StandardError.', { original_error: "ErrorWithTwoArgs", + instantiation_error_class: "ArgumentError", instantiation_error_message: "wrong number of arguments (given 1, expected 2)", }, ) end + it "falls back to StandardError when the client can't initialize the error class when initialize doesn't take a string" do + allow(Temporal.logger).to receive(:error) + + message = "An error message" + stack_trace = ["a fake backtrace"] + failure = Fabricate( + :api_application_failure, + message: message, + backtrace: stack_trace, + error_class: ErrorThatRaisesInInitialize.to_s, + ) + + e = Temporal::Workflow::Errors.generate_error(failure) + expect(e).to be_a(StandardError) + expect(e.message).to eq("ErrorThatRaisesInInitialize: An error message") + expect(e.backtrace).to eq(stack_trace) + expect(Temporal.logger) + .to have_received(:error) + .with( + 'Could not instantiate original error. Defaulting to StandardError.', + { + original_error: "ErrorThatRaisesInInitialize", + instantiation_error_class: "TypeError", + instantiation_error_message: "String can't be coerced into Integer", + }, + ) + end end end