Skip to content

Bug: sam build fails with "Fn::FindInMap layout is incorrect" when using AWS::LanguageExtensions with an unresolved !Ref parameter as a map key (regression in 1.160.0) #9004

Closed

Description

@polyomino24

Description:

sam build fails with Fn::FindInMap layout is incorrect when a template uses AWS::LanguageExtensions with Fn::FindInMap where a template parameter is used as a map key via !Ref, and no value is supplied for that parameter at build time (i.e., without --parameter-overrides and no Default defined).
This seems to be a regression introduced in 1.160.0 — the same template built successfully with 1.159.1.

Steps to reproduce:

  1. Create a new directory and add the following files:

samconfig.yaml

version: 0.1
stg:
  global:
    parameters:
      parameter_overrides:
        - ENV=stg

template.yaml

AWSTemplateFormatVersion: 2010-09-09
Transform:
  - AWS::Serverless-2016-10-31
  - AWS::LanguageExtensions

Parameters:
  ENV:
    Type: String
    AllowedValues: [stg, prod]

Resources:
  MyFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: .
      Handler: index.handler
      Runtime: nodejs22.x
      Role: !FindInMap [EnvConfig, !Ref ENV, IAM]

Mappings:
  EnvConfig:
    stg:
      IAM: arn:aws:iam::123456789012:role/lambda-role-stg
    prod:
      IAM: arn:aws:iam::123456789012:role/lambda-role-prod

index.js

export const handler = async (_event, _context) => {
  return {
    statusCode: 200,
    body: JSON.stringify({
      message: 'Hello World',
    }),
  }
}
  1. Run sam build in that directory with AWS SAM CLI v1.160.0

Observed result:

Show output
% sam build --debug      
2026-05-14 15:42:16,844 | Config file location:                                            
/Users/ta.ishikawa/sam-cli-bug/samconfig.yaml                                              
2026-05-14 15:42:16,849 | Loading configuration values from [default.['build'].parameters] 
(env.command_name.section) in config file at                                               
'/Users/ta.ishikawa/sam-cli-bug/samconfig.yaml'...                                         
2026-05-14 15:42:16,849 | Configuration values successfully loaded.                        
2026-05-14 15:42:16,850 | Configuration values are: {}                                     
2026-05-14 15:42:16,851 | Using SAM Template at                                            
/Users/ta.ishikawa/sam-cli-bug/template.yaml                                               
2026-05-14 15:42:16,852 | Empty parameter set ({})                                         
2026-05-14 15:42:16,876 | OSError occurred while reading TOML file: [Errno 2] No such file 
or directory: '/Users/ta.ishikawa/sam-cli-bug/samconfig.toml'                              
2026-05-14 15:42:16,877 | Using config file: samconfig.toml, config environment: default   
2026-05-14 15:42:16,878 | Expand command line arguments to:                                
2026-05-14 15:42:16,878 | --template_file=/Users/ta.ishikawa/sam-cli-bug/template.yaml     
--mount_with=READ --build_dir=.aws-sam/build --cache_dir=.aws-sam/cache                    
2026-05-14 15:42:16,941 | 'build' command is called                                        
2026-05-14 15:42:16,942 | Expanding CloudFormation Language Extensions (Phase 1)           
2026-05-14 15:42:16,943 | Processing Fn::ForEach constructs in template                    
2026-05-14 15:42:16,943 | Resolving intrinsic functions in template                        
2026-05-14 15:42:16,944 | Failed to expand CloudFormation Language Extensions:             
Fn::FindInMap layout is incorrect                                                          
2026-05-14 15:42:16,944 | Telemetry endpoint configured to be                              
https://aws-serverless-tools-telemetry.us-west-2.amazonaws.com/metrics                     
2026-05-14 15:42:17,004 | No container socket path in global storage, falling back to      
DOCKER_HOST detection:                                                                     
2026-05-14 15:42:17,005 | Telemetry endpoint configured to be                              
https://aws-serverless-tools-telemetry.us-west-2.amazonaws.com/metrics                     
2026-05-14 15:42:17,005 | Unable to find Click Context for getting session_id.             
2026-05-14 15:42:17,006 | No container socket path in global storage, falling back to      
DOCKER_HOST detection:                                                                     
2026-05-14 15:42:17,007 | Sending Telemetry: {'metrics': [{'commandRun': {'requestId':     
'b6466981-55a4-44ed-87e5-d630d5d362cd', 'installationId':                                  
'0fe4a75f-9858-4a11-99c0-5e7442a73e66', 'sessionId':                                       
'8baa53f2-54da-4d69-8f30-5c2f7c9fa5e7', 'executionEnvironment': 'CLI', 'ci': False,        
'pyversion': '3.13.11', 'samcliVersion': '1.160.0', 'osPlatform': 'Darwin',                
'awsProfileProvided': False, 'debugFlagProvided': True, 'region': '', 'commandName': 'sam  
build', 'metricSpecificAttributes': {'projectType': 'CFN', 'gitOrigin': None,              
'projectName': 'f9fbd5b7efdc83a3be25efdc23b036d1a8f30b42b0cd3d93878fb16d5ccb80a3',         
'initialCommit': None, 'containerEngine': 'docker-default', 'adminContainerPreference':    
None}, 'duration': 66, 'exitReason': 'InvalidSamDocumentException', 'exitCode': 255}}]}    
2026-05-14 15:42:17,007 | Sending Telemetry: {'metrics': [{'events': {'requestId':         
'cb03bbbc-7750-4173-bc4b-cd575edc9164', 'installationId':                                  
'0fe4a75f-9858-4a11-99c0-5e7442a73e66', 'sessionId':                                       
'8baa53f2-54da-4d69-8f30-5c2f7c9fa5e7', 'executionEnvironment': 'CLI', 'ci': False,        
'pyversion': '3.13.11', 'samcliVersion': '1.160.0', 'osPlatform': 'Darwin', 'commandName': 
'sam build', 'metricSpecificAttributes': {'events': [{'event_name':                        
'SamConfigFileExtension', 'event_value': '.yaml', 'thread_id':                             
'7b770acae30e4e35af06873f64ecae54', 'time_stamp': '2026-05-14 06:42:16.844088+00',         
'exception_name': None}, {'event_name': 'SamConfigFileExtension', 'event_value': '.toml',  
'thread_id': '2d863e0b995e4373b77a3a70a49b2d68', 'time_stamp': '2026-05-14                 
06:42:16.877624+00', 'exception_name': None}], 'containerEngine': 'docker-default'}}}]}    
2026-05-14 15:42:17,433 |                                                                  
HTTPSConnectionPool(host='aws-serverless-tools-telemetry.us-west-2.amazonaws.com',         
port=443): Read timed out. (read timeout=0.1)                                              
2026-05-14 15:42:17,435 |                                                                  
HTTPSConnectionPool(host='aws-serverless-tools-telemetry.us-west-2.amazonaws.com',         
port=443): Read timed out. (read timeout=0.1)                                              

Error: Fn::FindInMap layout is incorrect
Traceback:
  File "/Users/ta.ishikawa/.pyenv/versions/3.13.11/lib/python3.13/site-packages/click/core.py", line 1082, in main
    rv = self.invoke(ctx)
  File "/Users/ta.ishikawa/.pyenv/versions/3.13.11/lib/python3.13/site-packages/click/core.py", line 1697, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/Users/ta.ishikawa/.pyenv/versions/3.13.11/lib/python3.13/site-packages/click/core.py", line 1443, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ta.ishikawa/.pyenv/versions/3.13.11/lib/python3.13/site-packages/click/core.py", line 788, in invoke
    return __callback(*args, **kwargs)
  File "/Users/ta.ishikawa/.pyenv/versions/3.13.11/lib/python3.13/site-packages/samcli/cli/cli_config_file.py", line 366, in wrapper
    return func(*args, **kwargs)
  File "/Users/ta.ishikawa/.pyenv/versions/3.13.11/lib/python3.13/site-packages/click/decorators.py", line 92, in new_func
    return ctx.invoke(f, obj, *args, **kwargs)
           ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ta.ishikawa/.pyenv/versions/3.13.11/lib/python3.13/site-packages/click/core.py", line 788, in invoke
    return __callback(*args, **kwargs)
  File "/Users/ta.ishikawa/.pyenv/versions/3.13.11/lib/python3.13/site-packages/samcli/lib/telemetry/metric.py", line 190, in wrapped
    raise exception  # pylint: disable=raising-bad-type
    ^^^^^^^^^^^^^^^
  File "/Users/ta.ishikawa/.pyenv/versions/3.13.11/lib/python3.13/site-packages/samcli/lib/telemetry/metric.py", line 155, in wrapped
    return_value = func(*args, **kwargs)
  File "/Users/ta.ishikawa/.pyenv/versions/3.13.11/lib/python3.13/site-packages/samcli/lib/utils/version_checker.py", line 43, in wrapped
    actual_result = func(*args, **kwargs)
  File "/Users/ta.ishikawa/.pyenv/versions/3.13.11/lib/python3.13/site-packages/samcli/cli/main.py", line 95, in wrapper
    return func(*args, **kwargs)
  File "/Users/ta.ishikawa/.pyenv/versions/3.13.11/lib/python3.13/site-packages/samcli/commands/build/command.py", line 175, in cli
    do_cli(
    ~~~~~~^
        ctx,
        ^^^^
    ...<22 lines>...
        use_buildkit,
        ^^^^^^^^^^^^^
    )  # pragma: no cover
    ^
  File "/Users/ta.ishikawa/.pyenv/versions/3.13.11/lib/python3.13/site-packages/samcli/commands/build/command.py", line 244, in do_cli
    with BuildContext(
         ~~~~~~~~~~~~^
        function_identifier,
        ^^^^^^^^^^^^^^^^^^^^
    ...<22 lines>...
        use_buildkit=use_buildkit,
        ^^^^^^^^^^^^^^^^^^^^^^^^^^
    ) as ctx:
    ^
  File "/Users/ta.ishikawa/.pyenv/versions/3.13.11/lib/python3.13/site-packages/samcli/commands/build/build_context.py", line 202, in __enter__
    self.set_up()
    ~~~~~~~~~~~^^
  File "/Users/ta.ishikawa/.pyenv/versions/3.13.11/lib/python3.13/site-packages/samcli/commands/build/build_context.py", line 208, in set_up
    self._stacks, remote_stack_full_paths = SamLocalStackProvider.get_stacks(
                                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        self._template_file,
        ^^^^^^^^^^^^^^^^^^^^
        parameter_overrides=self._parameter_overrides,
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        global_parameter_overrides=self._global_parameter_overrides,
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/Users/ta.ishikawa/.pyenv/versions/3.13.11/lib/python3.13/site-packages/samcli/lib/providers/sam_stack_provider.py", line 274, in get_stacks
    lang_ext_result = expand_language_extensions(template_dict, parameter_values=parameter_values)
  File "/Users/ta.ishikawa/.pyenv/versions/3.13.11/lib/python3.13/site-packages/samcli/lib/cfn_language_extensions/sam_integration.py", line 555, in expand_language_extensions
    raise InvalidSamDocumentException(str(e)) from e

An unexpected error was encountered while executing "sam build".
Search for an existing issue:
https://github.com/aws/aws-sam-cli/issues?q=is%3Aissue+is%3Aopen+Bug%3A%20sam%20build%20-%20InvalidSamDocumentException
Or create a bug report:
https://github.com/aws/aws-sam-cli/issues/new?template=Bug_report.md&title=Bug%3A%20sam%20build%20-%20InvalidSamDocumentException

Expected result:

Build succeeds. sam build does not require --parameter-overrides — it should process the template in partial resolution mode, preserving Fn::FindInMap expressions whose keys cannot be resolved locally, and let CloudFormation resolve them at deploy time.

Additional environment details (Ex: Windows, Mac, Amazon Linux etc)

  1. OS: Mac
  2. sam --version: SAM CLI, version 1.160.0
  3. AWS region: ap-northeast-1
# Paste the output of `sam --info` here
{
  "version": "1.160.0",
  "system": {
    "python": "3.13.11",
    "os": "macOS-15.7.2-arm64-arm-64bit-Mach-O"
  },
  "additional_dependencies": {
    "container_engine": "Docker(v29.3.1)",
    "aws_cdk": "Not available",
    "terraform": "1.14.8"
  },
  "available_beta_feature_env_vars": [
    "SAM_CLI_BETA_FEATURES",
    "SAM_CLI_BETA_BUILD_PERFORMANCE",
    "SAM_CLI_BETA_TERRAFORM_SUPPORT",
    "SAM_CLI_BETA_PACKAGE_PERFORMANCE",
    "SAM_CLI_BETA_UV_PACKAGE_MANAGER"
  ]
}

Root cause analysis:

The bug is in samcli/lib/cfn_language_extensions/resolvers/fn_find_in_map.py.
When sam build is invoked without --parameter-overrides, the ENV parameter has no value in context.parameter_values and no Default in the template. FnRefResolver correctly returns {"Ref": "ENV"} (the unresolved dict) in PARTIAL mode. However, FnFindInMapResolver then validates the resolved key with isinstance(top_key, str) and unconditionally raises InvalidTemplateException regardless of resolution mode:

# Validate resolved keys are strings
if not isinstance(map_name, str):
raise InvalidTemplateException("Fn::FindInMap layout is incorrect")
if not isinstance(top_key, str):
raise InvalidTemplateException("Fn::FindInMap layout is incorrect")
if not isinstance(second_key, str):
raise InvalidTemplateException("Fn::FindInMap layout is incorrect")

This is inconsistent with FnRefResolver, which correctly handles the partial mode case:

if self.context.resolution_mode == ResolutionMode.FULL:
raise UnresolvableReferenceError("Ref", ref_target)
# In partial mode, preserve the reference
return {"Ref": ref_target}

Notably, ResolutionMode.PARTIAL is the documented default for SAM CLI integration (models.py: "Use this mode for SAM integration where resource references cannot be resolved locally"), and process_template_for_sam_cli explicitly sets resolution_mode=ResolutionMode.PARTIAL. The cfn_language_extensions module did not exist in 1.159.1, so this is a new regression (likely introduced by #8637).

Proposed Fix

In fn_find_in_map.py, mirror the FnRefResolver pattern — preserve the original Fn::FindInMap expression when in PARTIAL mode and a key cannot be resolved to a string:

# fn_find_in_map.py (proposed fix)
if not isinstance(map_name, str) or not isinstance(top_key, str) or not isinstance(second_key, str):
    from samcli.lib.cfn_language_extensions.models import ResolutionMode
    if self.context.resolution_mode == ResolutionMode.PARTIAL:
        return value  # preserve as-is; CloudFormation will resolve at deploy time
    raise InvalidTemplateException("Fn::FindInMap layout is incorrect")

Additional notes

  • sam validate passes on the same template (different code path, not affected by this bug)
  • Workaround: use sam build --config-env stg so ENV=stg is passed as a parameter override — but this breaks the common workflow of building once for all environments

Activity

  1. added
    stage/needs-triageAutomatically applied to new issues and PRs, indicating they haven't been looked at.
    on May 14, 2026
  2. roger-zhangg commented on May 14, 2026

    @roger-zhangg
    Member

    Thanks for reporting, we are taking a look now. In the meantime, you can downgrade to (https://github.com/aws/aws-sam-cli/releases/tag/v1.159.1) to unblock.

  3. bnusunny commented on May 14, 2026

    @bnusunny
    Contributor

    There tranform ordering is important. please move the AWS::LanguageExtensions before AWS::Serverless-2016-10-31.

    AWSTemplateFormatVersion: 2010-09-09
    Transform:
      - AWS::LanguageExtensions   
      - AWS::Serverless-2016-10-31
  4. bnusunny commented on May 14, 2026

    @bnusunny
    Contributor

    I can reproduce this issue and working on a fix.

  5. added and removed
    stage/needs-triageAutomatically applied to new issues and PRs, indicating they haven't been looked at.
    on May 14, 2026
  6. jkaraganis-bch commented on May 14, 2026

    @jkaraganis-bch

    Another workaround that worked for us and might be helpful for others:

    We were only including LanguageExtensions due to using Fn::ToJsonString for one parameter. We were able to replace that with a !Sub, remove LanguageExtensions from the Transform section and get our build working again.

  7. bnusunny commented on May 15, 2026

    @bnusunny
    Contributor
  8. github-actions commented on May 15, 2026

    @github-actions
    Contributor

    ⚠️COMMENT VISIBILITY WARNING⚠️

    Comments on closed issues are hard for our team to see.
    If you need more assistance, please either tag a team member or open a new issue that references this one.
    If you wish to keep having a conversation with other community members under this issue feel free to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions