I’ve had a Ruby 3.3 AWS Lambda function recently stop working sometime in the last couple of weeks. It seems that the function can no longer write to the tmp directory if the file size been added is above something like 10-40KB. The lambda function has Ephemeral storage set to 512MB so this doesn’t seem to be an issue.
To demonstrate the issue, I created a new Ruby lambda function which simple opens a file with open-uri. Files that were 2KB and 7KB worked fine, but any file much large (160KB) fails with an error.
I’m guessing a recent AWS change now requires us to set the tmp directory specifically but I’ve tried adding the TMPDIR environment variable and setting it directly in the code with ENV[‘TMPDIR’]= ‘/tmp’, none of which worked.
Working Example:
require "json"
require "open-uri"
def lambda_handler(event:, context:)
URI.open("https://freetestdata.com/wp-content/uploads/2023/11/7.7-KB.txt") # 7KB - works
URI.open("https://freetestdata.com/wp-content/uploads/2023/11/160-KB.txt") # 160KB - error
{ statusCode: 200, body: JSON.generate('Hello from Lambda!') }
end
Error Message:
system temporary path is world-writable: /tmp
/tmp is world-writable: /tmp
. is not writable: /var/task
Error raised from handler method
{
"errorMessage": "could not find a temporary directory",
"errorType": "Function<ArgumentError>",
"stackTrace": [
"/var/lang/lib/ruby/3.3.0/tmpdir.rb:43:in `tmpdir'",
"/var/lang/lib/ruby/3.3.0/tmpdir.rb:119:in `tmpdir'",
"/var/lang/lib/ruby/3.3.0/tmpdir.rb:142:in `create'",
"/var/lang/lib/ruby/3.3.0/tempfile.rb:157:in `initialize'",
"/var/lang/lib/ruby/3.3.0/open-uri.rb:414:in `new'",
"/var/lang/lib/ruby/3.3.0/open-uri.rb:414:in `<<'",
"/var/lang/lib/ruby/3.3.0/open-uri.rb:350:in `block (3 levels) in open_http'",
"/var/lang/lib/ruby/3.3.0/net/protocol.rb:535:in `call_block'",
"/var/lang/lib/ruby/3.3.0/net/protocol.rb:526:in `<<'",
"/var/lang/lib/ruby/3.3.0/net/http/response.rb:702:in `block (2 levels) in inflate_adapter'",
"/var/lang/lib/ruby/3.3.0/net/http/response.rb:700:in `inflate'",
"/var/lang/lib/ruby/3.3.0/net/http/response.rb:700:in `block in inflate_adapter'",
"/var/lang/lib/ruby/3.3.0/net/protocol.rb:535:in `call_block'",
"/var/lang/lib/ruby/3.3.0/net/protocol.rb:526:in `<<'",
"/var/lang/lib/ruby/3.3.0/net/protocol.rb:162:in `read'",
"/var/lang/lib/ruby/3.3.0/net/http/response.rb:723:in `read'",
"/var/lang/lib/ruby/3.3.0/net/http/response.rb:631:in `read_chunked'",
"/var/lang/lib/ruby/3.3.0/net/http/response.rb:595:in `block in read_body_0'",
"/var/lang/lib/ruby/3.3.0/net/http/response.rb:570:in `inflater'",
"/var/lang/lib/ruby/3.3.0/net/http/response.rb:593:in `read_body_0'",
"/var/lang/lib/ruby/3.3.0/net/http/response.rb:363:in `read_body'",
"/var/lang/lib/ruby/3.3.0/open-uri.rb:349:in `block (2 levels) in open_http'",
"/var/lang/lib/ruby/3.3.0/net/http.rb:2353:in `block in transport_request'",
"/var/lang/lib/ruby/3.3.0/net/http/response.rb:320:in `reading_body'",
"/var/lang/lib/ruby/3.3.0/net/http.rb:2352:in `transport_request'",
"/var/lang/lib/ruby/3.3.0/net/http.rb:2306:in `request'",
"/var/lang/lib/ruby/3.3.0/open-uri.rb:340:in `block in open_http'",
"/var/lang/lib/ruby/3.3.0/net/http.rb:1570:in `start'",
"/var/lang/lib/ruby/3.3.0/open-uri.rb:334:in `open_http'",
"/var/lang/lib/ruby/3.3.0/open-uri.rb:770:in `buffer_open'",
"/var/lang/lib/ruby/3.3.0/open-uri.rb:220:in `block in open_loop'",
"/var/lang/lib/ruby/3.3.0/open-uri.rb:218:in `catch'",
"/var/lang/lib/ruby/3.3.0/open-uri.rb:218:in `open_loop'",
"/var/lang/lib/ruby/3.3.0/open-uri.rb:158:in `open_uri'",
"/var/lang/lib/ruby/3.3.0/open-uri.rb:750:in `open'",
"/var/lang/lib/ruby/3.3.0/open-uri.rb:29:in `open'",
"/var/task/lambda_function.rb:5:in `lambda_handler'",
"/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric/lambda_handler.rb:28:in `call_handler'",
"/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric.rb:88:in `run_user_code'",
"/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric.rb:66:in `start_runtime_loop'",
"/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric.rb:49:in `run'",
"/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric.rb:221:in `bootstrap_handler'",
"/var/runtime/gems/aws_lambda_ric-3.0.0/lib/aws_lambda_ric.rb:203:in `start'",
"/var/runtime/index.rb:4:in `<main>'"
]
2
Answers
AWS has multiple runtime versions for Ruby 3.3. I was able to view the CloudWatch Logs and see that the function was failing when invoked with ruby:3.3.v12.
I went back through the CloudWatch logs to a version in July 2024 which was working, and copied the Runtime version ARN. Now, when viewing the function, you can "Edit runtime management configuration", select manual, and then set a specific Runtime version ARN.
AWS was using ruby:3.3.v9 in July 2024 which had the ARN:
In another month, I'll check if AWS is using a newer version of the runtime and switch back to Auto runtime updates to see if the issue is resolved.
Right now, this issue exists only with latest runtime
Ruby 3.3
, If you try withRuby 3.2
runtime it’ll work without any issues.The issue seems to be related to permissions. By default Ruby tries to write to system’s temp directory. If it’s not accessible or secure Ruby will try to write to current working directory.
So if we look at the error it says
system temporary path is world-writable: /tmp
which means Ruby thinks current folder permissions are not good enough to call it secure. So then it try’s to write to current working directory which we know is read-only in case of lambda do it throws this. is not writable: /var/task
.