4
votes

I have an AWS Lambda which is designed for direct invocation from multiple applications within my team's service landscape. I'm writing a wrapper class which will perform this invocation, and associated validation and error detection / handling in the Lambda's response.

By design, the Lambda terminates with an unhandled exception if runtime validation of the invocation parameters fails. But I didn't expect to find that in spite of an unhandled function error, the status_code of the invocation response is 200:

[1] pry(main)> lambda_client = Aws::Lambda::Client.new(region: 'us-east-1')
=> #<Aws::Lambda::Client>
[2] pry(main)> invocation_response = lambda_client.invoke(function_name: 'jwt-tokens-dev-AccessTokenCreator') 
=> #<struct Aws::Lambda::Types::InvocationResponse
 status_code=200,
 function_error="Unhandled",
 log_result=nil,
 payload=#<StringIO:0x007f91c1749028>,
 executed_version="$LATEST">
[3] pry(main)> invocation_response.payload.string
=> "{\"errorMessage\": \"Required parameters are missing: role, sub, sub_type\", \"errorType\": \"ParamMissingError\", \"stackTrace\": [[\"/var/task/handler.py\", 15, \"access_token_creator\", \"return access_token_creator_handler(event, context)\"], [\"/var/task/access_token_creator.py\", 32, \"handler\", \"params = _validate_event_params(event)\"], [\"/var/task/access_token_creator.py\", 97, \"_validate_event_params\", \"raise ParamMissingError('Required parameters are missing: %s' % ', '.join(missing_params))\"]]}"
[4] pry(main)> ActiveSupport::JSON.decode(invocation_response.payload.string)
=> {"errorMessage"=>"Required parameters are missing: role, sub, sub_type",
 "errorType"=>"ParamMissingError",
 "stackTrace"=>
  [["/var/task/handler.py", 15, "access_token_creator", "return access_token_creator_handler(event, context)"],
   ["/var/task/access_token_creator.py", 32, "handler", "params = _validate_event_params(event)"],
   ["/var/task/access_token_creator.py",
    97,
    "_validate_event_params",
    "raise ParamMissingError('Required parameters are missing: %s' % ', '.join(missing_params))"]]}

Is it expected that the status code of the response of a direct Lambda invocation would be 200, despite an unhandled function error? I want to implement proper error response detection in my wrapper class, and searching for the key "errorType" in the top-level of the JSON response doesn't really seem so robust.

1
There is already some discussion of Lambda errors and status codes, in the context of API Gateway Lambda integrations, in the documentation, on StackOverflow, and elsewhere --- but my use case is a direct Lambda invocation from application code. - Daniel B.
Confirmation that the 200 is expected, here: docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html ...4xx and 5xx are only used for request-related issues and service-related failures. If the function starts and finishes (for request/response, regardless of any reported error), that's a 200, presumably designed that way because your request to invoke was processed successfully. The fact that an error occurred does not mean the service itself failed or that the request was otherwise rejected. - Michael - sqlbot

1 Answers

3
votes

The solution -- too obvious, but not enough to distract from the "200" status_code -- is to check if function_error is nil.

The value is nil in the event of successful invocation:

[8] pry(main)> invocation_response = lambda_client.invoke(function_name: 'jwt-tokens-dev-AccessTokenCreator', payload: ActiveSupport::JSON::encode(sub:3285397, sub_type:'user', role:'admin'))
=> #<struct Aws::Lambda::Types::InvocationResponse
 status_code=200,
 function_error=nil,
 log_result=nil,
 payload=#<StringIO:0x007f91c2a2eeb8>,
 executed_version="$LATEST">

Otherwise it has the value 'Unhandled' or 'Handled':

function_error ⇒ String

Indicates whether an error occurred while executing the Lambda function. If an error occurred this field will have one of two values; Handled or Unhandled. Handled errors are errors that are reported by the function while the Unhandled errors are those detected and reported by AWS Lambda. Unhandled errors include out of memory errors and function timeouts. For information about how to report an Handled error, see Programming Model.

https://docs.aws.amazon.com/sdkforruby/api/Aws/Lambda/Types/InvocationResponse.html#function_error-instance_method