Skip to content

states:GetExecutionHistory fails in ruby3.4 Lambda environment #3231

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

Open
1 task
amancevice opened this issue Apr 8, 2025 · 6 comments
Open
1 task

states:GetExecutionHistory fails in ruby3.4 Lambda environment #3231

amancevice opened this issue Apr 8, 2025 · 6 comments
Labels
investigating Issue is being investigated

Comments

@amancevice
Copy link

Describe the bug

In the Lambda ruby3.4 runtime using the latest version of the aws-sdk-states gem, the states:GetExecutionHistory encounters a JSON parsing error if the execution history contains unicode characters.

Regression Issue

  • Select this option if this issue appears to be a regression.

Expected Behavior

Aws::States::Client.new.get_execution_history(execution_arn: 'arn:aws...') should succeed

Current Behavior

When a Step Function state machine's execution history contains an emdash (Unicode U+2014) the Ruby SDK throws an error parsing the JSON response.

/var/lang/lib/ruby/gems/3.4.0/gems/json-2.10.2/lib/json/common.rb:248:in 'String#encode': "\xE2" on US-ASCII (Encoding::InvalidByteSequenceError)

Reproduction Steps

  1. Create a state machine that contains an emdash (—) character in its output or variable assignment
  2. Create an execution for the state machine and take note of the execution ARN
  3. Open Lambda ruby3.4 runtime shell: docker run --rm -it --entrypoint=bash public.ecr.aws/lambda/ruby
  4. Install the states gem: gem install aws-sdk-states
  5. Open an IRB session: irb
  6. Try to get the execution history: Aws::States::Client.new.get_execution_history(execution_arn: 'arn:aws:...')
  7. See error

Possible Solution

No response

Additional Information/Context

No response

Gem name ('aws-sdk', 'aws-sdk-resources' or service gems like 'aws-sdk-s3') and its version

aws-sdk-states

Environment details (Version of Ruby, OS environment)

Lambda ruby3.4

@amancevice amancevice added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Apr 8, 2025
@mullermp
Copy link
Contributor

mullermp commented Apr 8, 2025

Thanks for opening an issue. The error appears to be in the JSON gem. Do you have a full SDK stack trace? You may want to consider opening an issue with the json maintainers. You can also try adding gem oj to your gemfile and use it as your preferred parser and see if that works.

@mullermp mullermp added investigating Issue is being investigated response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. and removed bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Apr 8, 2025
@amancevice
Copy link
Author

@mullermp thanks that makes sense. I wonder if this is instead a bug to file with the Lambda maintainers — maybe the ruby3.4 runtime needs to be updated to include the json and bigdecimal libraries (aws-sdk-dynamodb depends on bigdecimal). Is there a good place for me to file a ticket for them?

@mullermp
Copy link
Contributor

mullermp commented Apr 9, 2025

I'm not sure if it's a lambda issue either. What part of the code is calling .encode()? Can we try to get a root cause of why that can't be parsed with the json gem?

@amancevice
Copy link
Author

Here's a sample SAM template that can replicate the issue (forgive the overly-permissive IAM policy):

# template.yml
---
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: AWS Ruby SDK Test
Resources:
  Function:
    Type: AWS::Serverless::Function
    Properties:
      Architectures:
        - arm64
      CodeUri: .
      Description: Test aws-sdk-states
      Environment:
        Variables:
          STATE_MACHINE_ARN: !Ref StateMachine
      Handler: index.handler
      Policies:
        - Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Action: states:*
              Resource: "*"
      Runtime: ruby3.4
  StateMachine:
    Type: AWS::Serverless::StateMachine
    Properties:
      Definition:
        QueryLanguage: JSONata
        StartAt: Pass
        States:
          Pass:
            Type: Pass
            End: true
            Output:
              utf8: — # emdash character

And here's my Gemfile + index.rb:

# Gemfile
source 'https://rubygems.org'

gem 'aws-sdk-states'
# index.rb
require 'aws-sdk-states'

STATES = Aws::States::Client.new
STATE_MACHINE_ARN = ENV['STATE_MACHINE_ARN']

def handler(event:, context:)
  execution_arn = STATES.list_executions(state_machine_arn: STATE_MACHINE_ARN).executions.first.execution_arn
  STATES.get_execution_history(execution_arn:)
end

And here is the result of invoking the Lambda:

{
  "errorMessage": "\"\\xE2\" on US-ASCII",
  "errorType": "Function<Encoding::InvalidByteSequenceError>",
  "stackTrace": [
    "/var/lang/lib/ruby/3.4.0/json/common.rb:221:in 'String#encode'",
    "/var/lang/lib/ruby/3.4.0/json/common.rb:221:in 'JSON::Ext::Parser.parse'",
    "/var/lang/lib/ruby/3.4.0/json/common.rb:221:in 'JSON.parse'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/json/json_engine.rb:10:in 'Aws::Json::JsonEngine.load'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/json.rb:43:in 'Aws::Json.load'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/json/parser.rb:22:in 'Aws::Json::Parser#parse'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/json/handler.rb:65:in 'Aws::Json::Handler#parse_body'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/json/handler.rb:37:in 'Aws::Json::Handler#parse_response'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/json/handler.rb:14:in 'block in Aws::Json::Handler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/seahorse/client/response.rb:52:in 'block in Seahorse::Client::Response#on'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/seahorse/client/http/response.rb:146:in 'block in Seahorse::Client::Http::Response#on_success'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/seahorse/client/http/response.rb:173:in 'block in Seahorse::Client::Http::Response#listener'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/seahorse/client/http/response.rb:137:in 'Seahorse::Client::Http::Response#on_done'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/seahorse/client/http/response.rb:144:in 'Seahorse::Client::Http::Response#on_success'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/seahorse/client/response.rb:51:in 'Seahorse::Client::Response#on'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/json/handler.rb:14:in 'Aws::Json::Handler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/recursion_detection.rb:18:in 'Aws::Plugins::RecursionDetection::Handler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-states-1.87.0/lib/aws-sdk-states/plugins/endpoints.rb:43:in 'block in Aws::States::Plugins::Endpoints::Handler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/user_agent.rb:69:in 'Aws::Plugins::UserAgent.metric'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-states-1.87.0/lib/aws-sdk-states/plugins/endpoints.rb:57:in 'Aws::States::Plugins::Endpoints::Handler#with_metrics'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-states-1.87.0/lib/aws-sdk-states/plugins/endpoints.rb:43:in 'Aws::States::Plugins::Endpoints::Handler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/endpoint_discovery.rb:84:in 'Aws::Plugins::EndpointDiscovery::Handler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/seahorse/client/plugins/endpoint.rb:46:in 'Seahorse::Client::Plugins::Endpoint::Handler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/param_validator.rb:26:in 'Aws::Plugins::ParamValidator::Handler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/seahorse/client/plugins/raise_response_errors.rb:16:in 'Seahorse::Client::Plugins::RaiseResponseErrors::Handler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/checksum_algorithm.rb:169:in 'Aws::Plugins::ChecksumAlgorithm::OptionHandler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/jsonvalue_converter.rb:16:in 'Aws::Plugins::JsonvalueConverter::Handler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/invocation_id.rb:16:in 'Aws::Plugins::InvocationId::Handler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/idempotency_token.rb:19:in 'Aws::Plugins::IdempotencyToken::Handler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/param_converter.rb:26:in 'Aws::Plugins::ParamConverter::Handler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/seahorse/client/plugins/request_callback.rb:89:in 'Seahorse::Client::Plugins::RequestCallback::OptionHandler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/response_paging.rb:12:in 'Aws::Plugins::ResponsePaging::Handler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/seahorse/client/plugins/response_target.rb:24:in 'Seahorse::Client::Plugins::ResponseTarget::Handler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/telemetry.rb:39:in 'block in Aws::Plugins::Telemetry::Handler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/telemetry/no_op.rb:29:in 'Aws::Telemetry::NoOpTracer#in_span'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/telemetry.rb:53:in 'Aws::Plugins::Telemetry::Handler#span_wrapper'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/telemetry.rb:39:in 'Aws::Plugins::Telemetry::Handler#call'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-core-3.219.0/lib/seahorse/client/request.rb:72:in 'Seahorse::Client::Request#send_request'",
    "/var/runtime/ruby/3.4.0/gems/aws-sdk-states-1.87.0/lib/aws-sdk-states/client.rb:1721:in 'Aws::States::Client#get_execution_history'",
    "/var/task/index.rb:8:in 'Object#handler'",
    "/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric/lambda_handler.rb:28:in 'LambdaHandler#call_handler'",
    "/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric.rb:86:in 'AwsLambdaRIC::LambdaRunner#run_user_code'",
    "/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric.rb:64:in 'AwsLambdaRIC::LambdaRunner#start_runtime_loop'",
    "/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric.rb:47:in 'AwsLambdaRIC::LambdaRunner#run'",
    "/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric.rb:219:in 'AwsLambdaRIC::Bootstrap#bootstrap_handler'",
    "/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric.rb:201:in 'AwsLambdaRIC::Bootstrap#start'",
    "/var/runtime/index.rb:4:in '<main>'"
  ]
}

@github-actions github-actions bot removed the response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. label Apr 10, 2025
@jterapin
Copy link
Contributor

This issue looks very familiar to what I encountered last year with the json gem. See: ruby/json#697

I will test with your reproduction to see if I can replicate the error. In the mean time, have you tried using a different json engine like oj as mullermp mentioned? To see if the similar error surfaces?

@jterapin jterapin added the response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. label Apr 15, 2025
@amancevice
Copy link
Author

amancevice commented Apr 15, 2025

I've tried but I'm doing something wrong with SAM — Lambda returns cannot load such file -- oj

After adding the oj gem to the Gemfile & building with sam build --use-container I was able to get it to work. Still, I think it's suboptimal for the default Ruby v3.4 runtime for Lambda to have trouble executing AWS SDK ops out of the box

@github-actions github-actions bot removed the response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. label Apr 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
investigating Issue is being investigated
Projects
None yet
Development

No branches or pull requests

3 participants