Search code examples
amazon-web-servicesaws-samaws-sam-cli

AWS SAM starting local api returns "Function name is required" error


We are using CDK to build our infrastructure configuration. Moreover, I create my template.yml for SAM with cdk synth <stack_name> --no-staging > template.yml if it helps. I am using AWS Toolkit to invoke/debug my lambda functions on Intellij which works fine. However, if I run sam local start-api on terminal and send a request to one of my functions then it returns an error with stacktrace;

Traceback (most recent call last):
  File "/usr/local/Cellar/aws-sam-cli/0.53.0/libexec/lib/python3.7/site-packages/flask/app.py", line 2317, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/Cellar/aws-sam-cli/0.53.0/libexec/lib/python3.7/site-packages/flask/app.py", line 1840, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/Cellar/aws-sam-cli/0.53.0/libexec/lib/python3.7/site-packages/flask/app.py", line 1743, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/Cellar/aws-sam-cli/0.53.0/libexec/lib/python3.7/site-packages/flask/_compat.py", line 36, in reraise
    raise value
  File "/usr/local/Cellar/aws-sam-cli/0.53.0/libexec/lib/python3.7/site-packages/flask/app.py", line 1838, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/Cellar/aws-sam-cli/0.53.0/libexec/lib/python3.7/site-packages/flask/app.py", line 1824, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/usr/local/Cellar/aws-sam-cli/0.53.0/libexec/lib/python3.7/site-packages/samcli/local/apigw/local_apigw_service.py", line 203, in _request_handler
    self.lambda_runner.invoke(route.function_name, event, stdout=stdout_stream_writer, stderr=self.stderr)
  File "/usr/local/Cellar/aws-sam-cli/0.53.0/libexec/lib/python3.7/site-packages/samcli/commands/local/lib/local_lambda.py", line 84, in invoke
    function = self.provider.get(function_name)
  File "/usr/local/Cellar/aws-sam-cli/0.53.0/libexec/lib/python3.7/site-packages/samcli/lib/providers/sam_function_provider.py", line 65, in get
    raise ValueError("Function name is required")
ValueError: Function name is required

This is the command I run

sam local start-api --env-vars env.json --docker-network test

which gives the output

Mounting None at http://127.0.0.1:3000/v1 [GET, OPTIONS, POST]
Mounting None at http://127.0.0.1:3000/v1/user [GET, OPTIONS, POST]
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
2020-08-22 16:32:46  * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)
2020-08-22 16:33:03 Exception on /v1/user [OPTIONS]

And here is the env.json I am using as environment variables for my functions

{
  "tenantGetV1Function54F63CB9": {
    "db": "alpha",
    "connectionString": "mongodb://mongo"
  },
  "tenantPostV1FunctionA56822D0": {
    "db": "alpha",
    "connectionString": "mongodb://mongo"
  },
  "userGetV1Function7E6E55C2": {
    "db": "alpha",
    "connectionString": "mongodb://mongo"
  },
  "userPostV1FunctionEB035EB0": {
    "db": "alpha",
    "connectionString": "mongodb://mongo"
  }
}

I am also running Docker Desktop on macOS operating system.

EDIT: Here you can find the simplified template.yml with only one endpoint (one function definition) which is for tenantGetV1Function54F63CB9 function. It will map to GET /v1 endpoint. I didnt want include the whole template for 4 functions which makes around a thousand lines of .yml code.

https://gist.github.com/flexelem/d887136484d508e313e0a745c30a2d97


Solution

  • The problem solved if I create LambdaIntegration by passing the Function instance instead of its Alias instance in CDK. So, we are creating lambdas along with an alias. Then, we pass the alias to their associated Resource instance from Api Gateway.

    This is the way are creating;

    Function tenantGetV1Function = Function.Builder.create(this, "tenantGetV1Function")
        .role(roleLambda)
        .runtime(Runtime.JAVA_8)
        .code(lambdaCode)
        .handler("com.yolda.tenant.lambda.GetTenantHandler::handleRequest")
        .memorySize(512)
        .timeout(Duration.minutes(1))
        .environment(environment)
        .description(Instant.now().toString())
        .build();
    
    Alias tenantGetV1Alias = Alias.Builder.create(this, "tenantGetV1Alias")
        .aliasName("live")
        .version(tenantAdminGetV1Function.getCurrentVersion())
        .provisionedConcurrentExecutions(provisionedConcurrency)
        .build();
    
    Resource v1Resource = v1Resource.addResource("{tenantId}");
    v1Resource.addMethod("GET", LambdaIntegration.Builder.create(tenantGetV1Alias).build(), options);
    

    And if I replace tenantGetV1Alias with tenantGetV1Function then sam build command successfully builds all the functions which will make sam local start-api to spin up them.

    Resource v1Resource = v1Resource.addResource("{tenantId}");
    v1Resource.addMethod("GET", LambdaIntegration.Builder.create(tenantGetV1Function).build(), options);
    

    Somehow, SAM is not able to get function name property from CloudFormation templates if we assign aliases.