Skip to content

Commit 75858d8

Browse files
authored
Lambda: Proper error handling for code in S3 (#12883)
1 parent 71c610e commit 75858d8

File tree

4 files changed

+131
-3
lines changed

4 files changed

+131
-3
lines changed

localstack-core/localstack/services/lambda_/invocation/lambda_service.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -645,9 +645,15 @@ def store_s3_bucket_archive(
645645
return create_hot_reloading_code(path=archive_key)
646646
s3_client: "S3Client" = connect_to().s3
647647
kwargs = {"VersionId": archive_version} if archive_version else {}
648-
archive_file = s3_client.get_object(Bucket=archive_bucket, Key=archive_key, **kwargs)[
649-
"Body"
650-
].read()
648+
try:
649+
archive_file = s3_client.get_object(Bucket=archive_bucket, Key=archive_key, **kwargs)[
650+
"Body"
651+
].read()
652+
except s3_client.exceptions.ClientError as e:
653+
raise InvalidParameterValueException(
654+
f"Error occurred while GetObject. S3 Error Code: {e.response['Error']['Code']}. S3 Error Message: {e.response['Error']['Message']}",
655+
Type="User",
656+
)
651657
return store_lambda_archive(
652658
archive_file, function_name=function_name, region_name=region_name, account_id=account_id
653659
)

tests/aws/services/lambda_/test_lambda_api.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,66 @@ def test_lambda_code_location_s3(
653653
== get_function_response_updated["Configuration"]["CodeSize"]
654654
)
655655

656+
@markers.aws.validated
657+
def test_lambda_code_location_s3_errors(
658+
self, s3_bucket, snapshot, lambda_su_role, aws_client, create_lambda_function_aws
659+
):
660+
function_name = f"code-function-{short_uid()}"
661+
bucket_key = "code/code-function.zip"
662+
zip_file_bytes = create_lambda_archive(load_file(TEST_LAMBDA_PYTHON_ECHO), get_content=True)
663+
aws_client.s3.upload_fileobj(
664+
Fileobj=io.BytesIO(zip_file_bytes), Bucket=s3_bucket, Key=bucket_key
665+
)
666+
667+
# try to create the function with invalid bucket path
668+
with pytest.raises(ClientError) as e:
669+
aws_client.lambda_.create_function(
670+
FunctionName=function_name,
671+
Handler="index.handler",
672+
Code={
673+
"S3Bucket": f"some-random-non-existent-bucket-{short_uid()}",
674+
"S3Key": bucket_key,
675+
},
676+
PackageType="Zip",
677+
Role=lambda_su_role,
678+
Runtime=Runtime.python3_12,
679+
)
680+
snapshot.match("create-error-wrong-bucket", e.value.response)
681+
682+
with pytest.raises(ClientError) as e:
683+
aws_client.lambda_.create_function(
684+
FunctionName=function_name,
685+
Handler="index.handler",
686+
Code={"S3Bucket": s3_bucket, "S3Key": "non/existent.zip"},
687+
PackageType="Zip",
688+
Role=lambda_su_role,
689+
Runtime=Runtime.python3_12,
690+
)
691+
snapshot.match("create-error-wrong-key", e.value.response)
692+
693+
create_lambda_function_aws(
694+
FunctionName=function_name,
695+
Handler="index.handler",
696+
Code={"S3Bucket": s3_bucket, "S3Key": bucket_key},
697+
PackageType="Zip",
698+
Role=lambda_su_role,
699+
Runtime=Runtime.python3_12,
700+
)
701+
702+
with pytest.raises(ClientError) as e:
703+
aws_client.lambda_.update_function_code(
704+
FunctionName=function_name,
705+
S3Bucket=f"some-random-non-existent-bucket-{short_uid()}",
706+
S3Key=bucket_key,
707+
)
708+
snapshot.match("update-error-wrong-bucket", e.value.response)
709+
710+
with pytest.raises(ClientError) as e:
711+
aws_client.lambda_.update_function_code(
712+
FunctionName=function_name, S3Bucket=s3_bucket, S3Key="non/existent.zip"
713+
)
714+
snapshot.match("update-error-wrong-key", e.value.response)
715+
656716
# TODO: fix type of AccessDeniedException yielding null
657717
@markers.snapshot.skip_snapshot_verify(
658718
paths=[

tests/aws/services/lambda_/test_lambda_api.snapshot.json

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19000,5 +19000,58 @@
1900019000
}
1900119001
}
1900219002
}
19003+
},
19004+
"tests/aws/services/lambda_/test_lambda_api.py::TestLambdaFunction::test_lambda_code_location_s3_errors": {
19005+
"recorded-date": "21-07-2025, 17:45:01",
19006+
"recorded-content": {
19007+
"create-error-wrong-bucket": {
19008+
"Error": {
19009+
"Code": "InvalidParameterValueException",
19010+
"Message": "Error occurred while GetObject. S3 Error Code: NoSuchBucket. S3 Error Message: The specified bucket does not exist"
19011+
},
19012+
"Type": "User",
19013+
"message": "Error occurred while GetObject. S3 Error Code: NoSuchBucket. S3 Error Message: The specified bucket does not exist",
19014+
"ResponseMetadata": {
19015+
"HTTPHeaders": {},
19016+
"HTTPStatusCode": 400
19017+
}
19018+
},
19019+
"create-error-wrong-key": {
19020+
"Error": {
19021+
"Code": "InvalidParameterValueException",
19022+
"Message": "Error occurred while GetObject. S3 Error Code: NoSuchKey. S3 Error Message: The specified key does not exist."
19023+
},
19024+
"Type": "User",
19025+
"message": "Error occurred while GetObject. S3 Error Code: NoSuchKey. S3 Error Message: The specified key does not exist.",
19026+
"ResponseMetadata": {
19027+
"HTTPHeaders": {},
19028+
"HTTPStatusCode": 400
19029+
}
19030+
},
19031+
"update-error-wrong-bucket": {
19032+
"Error": {
19033+
"Code": "InvalidParameterValueException",
19034+
"Message": "Error occurred while GetObject. S3 Error Code: NoSuchBucket. S3 Error Message: The specified bucket does not exist"
19035+
},
19036+
"Type": "User",
19037+
"message": "Error occurred while GetObject. S3 Error Code: NoSuchBucket. S3 Error Message: The specified bucket does not exist",
19038+
"ResponseMetadata": {
19039+
"HTTPHeaders": {},
19040+
"HTTPStatusCode": 400
19041+
}
19042+
},
19043+
"update-error-wrong-key": {
19044+
"Error": {
19045+
"Code": "InvalidParameterValueException",
19046+
"Message": "Error occurred while GetObject. S3 Error Code: NoSuchKey. S3 Error Message: The specified key does not exist."
19047+
},
19048+
"Type": "User",
19049+
"message": "Error occurred while GetObject. S3 Error Code: NoSuchKey. S3 Error Message: The specified key does not exist.",
19050+
"ResponseMetadata": {
19051+
"HTTPHeaders": {},
19052+
"HTTPStatusCode": 400
19053+
}
19054+
}
19055+
}
1900319056
}
1900419057
}

tests/aws/services/lambda_/test_lambda_api.validation.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,15 @@
371371
"tests/aws/services/lambda_/test_lambda_api.py::TestLambdaFunction::test_lambda_code_location_s3": {
372372
"last_validated_date": "2024-09-12T11:29:56+00:00"
373373
},
374+
"tests/aws/services/lambda_/test_lambda_api.py::TestLambdaFunction::test_lambda_code_location_s3_errors": {
375+
"last_validated_date": "2025-07-21T17:45:02+00:00",
376+
"durations_in_seconds": {
377+
"setup": 13.8,
378+
"call": 2.63,
379+
"teardown": 1.73,
380+
"total": 18.16
381+
}
382+
},
374383
"tests/aws/services/lambda_/test_lambda_api.py::TestLambdaFunction::test_lambda_code_location_zipfile": {
375384
"last_validated_date": "2024-09-12T11:29:52+00:00"
376385
},

0 commit comments

Comments
 (0)