Description:
When a template uses AWS::LanguageExtensions as a transform and has an AWS::Lambda::Function resource with inline ZipFile code containing !Sub (to interpolate ${AWS::Region} or ${AWS::AccountId}), sam build evaluates the Fn::Sub at build time rather than leaving it as a CloudFormation intrinsic for deployment-time resolution.
The result is that the built template has the substitutions baked in using whatever defaults the build environment has — typically us-east-1 for region and 123456789012 for account ID — instead of the actual deployment target values. The Fn::Sub wrapper is stripped entirely from the built template.
This is a regression introduced in 1.160.0 alongside the in-tree CloudFormation Language Extensions resolver.
Steps to reproduce:
- Create
template.yaml:
Transform:
- AWS::LanguageExtensions
- AWS::Serverless-2016-10-31
Resources:
MyTriggerFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: my-trigger
Runtime: python3.11
Handler: index.handler
Role: !Sub 'arn:aws:iam::${AWS::AccountId}:role/my-role'
Code:
ZipFile: !Sub |
import boto3
def handler(event, context):
client = boto3.client('stepfunctions')
client.start_execution(
stateMachineArn='arn:aws:states:${AWS::Region}:${AWS::AccountId}:stateMachine:my-state-machine',
)
- Run
sam build
- Inspect
.aws-sam/build/template.yaml
Observed result:
The built template has Fn::Sub stripped and ${AWS::Region} / ${AWS::AccountId} resolved to build-time defaults:
Code:
ZipFile: "import boto3\ndef handler(event, context):\n client = boto3.client('stepfunctions')\n\
\ client.start_execution(\n stateMachineArn='arn:aws:states:us-east-1:123456789012:stateMachine:my-state-machine',\n\
\ )\n"
Note: Fn::Sub in other parts of the template (e.g. Role: !Sub '...') is correctly preserved as a CloudFormation intrinsic and not evaluated at build time.
Expected result:
The built template should preserve Fn::Sub as a CloudFormation intrinsic, identical to the behaviour in 1.148.0:
Code:
ZipFile:
Fn::Sub: "import boto3\ndef handler(event, context):\n client = boto3.client('stepfunctions')\n\
\ client.start_execution(\n stateMachineArn='arn:aws:states:${AWS::Region}:${AWS::AccountId}:stateMachine:my-state-machine',\n\
\ )\n"
CloudFormation should then resolve ${AWS::Region} and ${AWS::AccountId} to the actual deployment region and account at stack create/update time.
Additional environment details
Working: SAM CLI 1.148.0
Broken: SAM CLI 1.160.0, 1.160.1
The regression appears to be tied to the introduction of the in-tree cfn_language_extensions resolver in 1.160.0 (see #9010 for a related fix in the same area). The template must have AWS::LanguageExtensions in its Transform list to trigger the issue — templates without it are unaffected.
- OS: macOS (arm64)
sam --version: 1.160.1 (broken), 1.148.0 (working)
- AWS region: ap-southeast-2
SAM 1.160.1:
{
"version": "1.160.1",
"system": {
"python": "3.13.9",
"os": "macOS-26.5-arm64-arm-64bit-Mach-O"
}
}
SAM 1.148.0:
{
"version": "1.148.0",
"system": {
"python": "3.11.10",
"os": "macOS-26.5-arm64-arm-64bit"
}
}
Description:
When a template uses
AWS::LanguageExtensionsas a transform and has anAWS::Lambda::Functionresource with inlineZipFilecode containing!Sub(to interpolate${AWS::Region}or${AWS::AccountId}),sam buildevaluates theFn::Subat build time rather than leaving it as a CloudFormation intrinsic for deployment-time resolution.The result is that the built template has the substitutions baked in using whatever defaults the build environment has — typically
us-east-1for region and123456789012for account ID — instead of the actual deployment target values. TheFn::Subwrapper is stripped entirely from the built template.This is a regression introduced in 1.160.0 alongside the in-tree CloudFormation Language Extensions resolver.
Steps to reproduce:
template.yaml:sam build.aws-sam/build/template.yamlObserved result:
The built template has
Fn::Substripped and${AWS::Region}/${AWS::AccountId}resolved to build-time defaults:Note:
Fn::Subin other parts of the template (e.g.Role: !Sub '...') is correctly preserved as a CloudFormation intrinsic and not evaluated at build time.Expected result:
The built template should preserve
Fn::Subas a CloudFormation intrinsic, identical to the behaviour in 1.148.0:CloudFormation should then resolve
${AWS::Region}and${AWS::AccountId}to the actual deployment region and account at stack create/update time.Additional environment details
Working: SAM CLI 1.148.0
Broken: SAM CLI 1.160.0, 1.160.1
The regression appears to be tied to the introduction of the in-tree
cfn_language_extensionsresolver in 1.160.0 (see #9010 for a related fix in the same area). The template must haveAWS::LanguageExtensionsin itsTransformlist to trigger the issue — templates without it are unaffected.sam --version: 1.160.1 (broken), 1.148.0 (working)SAM 1.160.1:
{ "version": "1.160.1", "system": { "python": "3.13.9", "os": "macOS-26.5-arm64-arm-64bit-Mach-O" } }SAM 1.148.0:
{ "version": "1.148.0", "system": { "python": "3.11.10", "os": "macOS-26.5-arm64-arm-64bit" } }