2727from samcli .local .docker .exceptions import PortAlreadyInUse
2828from samcli .local .docker .lambda_image import LambdaImage
2929from samcli .local .docker .manager import ContainerManager
30+ from samcli .local .lambdafn .exceptions import FunctionNotFound
3031from samcli .local .lambdafn .runtime import LambdaRuntime , WarmLambdaRuntime
3132from samcli .local .layers .layer_downloader import LayerDownloader
3233
@@ -98,6 +99,7 @@ def __init__(
9899 invoke_images : Optional [str ] = None ,
99100 mount_symlinks : Optional [bool ] = False ,
100101 no_mem_limit : Optional [bool ] = False ,
102+ function_logical_ids : Optional [Tuple [str , ...]] = None ,
101103 ) -> None :
102104 """
103105 Initialize the context
@@ -107,7 +109,7 @@ def __init__(
107109 template_file str
108110 Name or path to template
109111 function_identifier str
110- Identifier of the function to invoke
112+ Identifier of the single function to invoke (used by 'sam local invoke' command)
111113 env_vars_file str
112114 Path to a file containing values for environment variables
113115 docker_volume_basedir str
@@ -154,10 +156,27 @@ def __init__(
154156 Optional. A dictionary that defines the custom invoke image URI of each function
155157 mount_symlinks bool
156158 Optional. Indicates if symlinks should be mounted inside the container
159+ function_logical_ids tuple(str)
160+ Optional. Tuple of function logical IDs to filter and make available for local execution.
161+ Used by 'sam local start-api' and 'sam local start-lambda' commands to limit which
162+ functions from the template are exposed. If not provided, all functions are available.
157163 """
158164
159165 self ._template_file = template_file
160166 self ._function_identifier = function_identifier
167+ self ._function_logical_ids = function_logical_ids
168+
169+ # Validate that function_identifier and function_logical_ids aren't both provided
170+ # function_identifier is for 'sam local invoke' (single function)
171+ # function_logical_ids is for 'sam local start-lambda' commands (multiple function filter)
172+ if self ._function_identifier and self ._function_logical_ids :
173+ LOG .warning (
174+ "Both function_identifier and function_logical_ids were provided. "
175+ "function_identifier is used for 'sam local invoke' to specify a single function, "
176+ "while function_logical_ids is used for 'sam local start-lambda' to filter functions. "
177+ "function_identifier will take precedence for single function invocation."
178+ )
179+
161180 self ._env_vars_file = env_vars_file
162181 self ._docker_volume_basedir = docker_volume_basedir
163182 self ._docker_network = docker_network
@@ -241,10 +260,18 @@ def __enter__(self) -> "InvokeContext":
241260 if self ._docker_volume_basedir :
242261 _function_providers_args [self ._containers_mode ].append (True )
243262
263+ _function_providers_kwargs : Dict [str , Any ] = {}
264+
265+ if self ._function_logical_ids :
266+ _function_providers_kwargs ["function_logical_ids" ] = self ._function_logical_ids
267+
244268 self ._function_provider = _function_providers_class [self ._containers_mode ](
245- * _function_providers_args [self ._containers_mode ]
269+ * _function_providers_args [self ._containers_mode ], ** _function_providers_kwargs
246270 )
247271
272+ # Validate function logical IDs after provider is initialized
273+ self ._validate_function_logical_ids ()
274+
248275 self ._env_vars_value = self ._get_env_vars_value (self ._env_vars_file )
249276 self ._container_env_vars_value = self ._get_env_vars_value (self ._container_env_vars_file )
250277 self ._log_file_handle = self ._setup_log_file (self ._log_file )
@@ -448,6 +475,38 @@ def _clean_running_containers_and_related_resources(self) -> None:
448475 cast (WarmLambdaRuntime , self .lambda_runtime ).clean_running_containers_and_related_resources ()
449476 cast (RefreshableSamFunctionProvider , self ._function_provider ).stop_observer ()
450477
478+ def _validate_function_logical_ids (self ) -> None :
479+ """
480+ Validates that all provided function logical IDs exist in the template.
481+ Raises FunctionNotFound with helpful error message if validation fails.
482+ """
483+ if not self ._function_logical_ids :
484+ return # No filtering requested
485+
486+ # Get all available function names/IDs from the provider
487+ all_functions_set = set ()
488+ for func in self ._function_provider .get_all ():
489+ all_functions_set .add (func .name )
490+ all_functions_set .add (func .function_id )
491+ if func .functionname :
492+ all_functions_set .add (func .functionname )
493+
494+ # Check for invalid IDs
495+ invalid_ids = set (self ._function_logical_ids ) - all_functions_set
496+
497+ if invalid_ids :
498+ # Get all available function full paths, matching sam local invoke pattern
499+ all_function_full_paths = [f .full_path for f in self ._function_provider .get_all ()]
500+
501+ # Format message to match sam local invoke pattern exactly
502+ invalid_functions_str = ", " .join (sorted (invalid_ids ))
503+ available_function_message = "{} not found. Possible options in your template: {}" .format (
504+ invalid_functions_str , all_function_full_paths
505+ )
506+ LOG .info (available_function_message )
507+
508+ raise FunctionNotFound ("Unable to find Function(s) with name(s) '{}'" .format (invalid_functions_str ))
509+
451510 def _add_account_id_to_global (self ) -> None :
452511 """
453512 Attempts to get the Account ID from the current session
@@ -556,6 +615,21 @@ def initialized_container_ids(self) -> List[str]:
556615 """
557616 return self ._initialized_container_ids
558617
618+ @property
619+ def function_logical_ids (self ) -> Optional [Tuple [str , ...]]:
620+ """
621+ Returns the tuple of function logical IDs to filter, if provided.
622+
623+ This is used by 'sam local start-lambda' commands
624+ to limit which functions from the template are made available for local execution.
625+ This is different from function_identifier which is used by 'sam local invoke'
626+ to specify a single function to invoke.
627+
628+ Returns:
629+ Optional[Tuple[str, ...]]: Tuple of function logical IDs or None if no filter
630+ """
631+ return self ._function_logical_ids
632+
559633 @property
560634 def stdout (self ) -> StreamWriter :
561635 """
0 commit comments