aws / aws/aws-cdk

API Gateway & Lambda: Unable to delete Lambda function from AWS API Gateway (Lambda still in use by API Gateway)

Open
#30,658 3 comments 0 reactions 0 assignees View on GitHub
@aws-cdk/aws-lambda bug effort/medium p3
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

### Describe the bug

What I'm trying to do, is remove a Lambda Function from the API Gateway. I don't want to delete the whole Lambda Function itself (though that's not even possible when I try to).

I try to do this by simply commenting out the line of code that adds the Lambda Function to the API Gateway.

Here is my ApiGatewayStack:

```typescript
import { Stack } from "aws-cdk-lib";
import { Construct } from "constructs";
import { StackPropsConfig } from "../config/stackPropsConfig";
import { Deployment, DomainName, EndpointType, LambdaIntegration, RestApi, Stage } from "aws-cdk-lib/aws-apigateway";
import { IHostedZone } from "aws-cdk-lib/aws-route53";
import { ICertificate } from "aws-cdk-lib/aws-certificatemanager";

interface ApiGatewayProps extends StackPropsConfig {
hostedZone: IHostedZone;
certificate: ICertificate;
testLambda: LambdaIntegration;
createPost: LambdaIntegration;
getPost: LambdaIntegration;
}

export class ApiGatewayStack extends Stack {
public readonly customDomain: DomainName;

constructor(scope: Construct, id: string, props: ApiGatewayProps) {
super(scope, id, props);

const apiGateway = new RestApi(this, `butlai-api-gateway-${props.config.ENV}`, {
deploy: false
});

this.customDomain = apiGateway.addDomainName(`butlai-api-gateway-custom-domain-${props.config.ENV}`, {
domainName: props.config.ENV_URL,
certificate: props.certificate,
endpointType: EndpointType.EDGE,
});

// Explicitly create a deployment for v1
const deploymentV1 = new Deployment(this, `butlai-api-deployment-v1-${props.config.ENV}-${Date.now()}`, {
api: apiGateway,
retainDeployments: true,
});

// Create a stage for v1
new Stage(this, `butlai-api-stage-v1-${props.config.ENV}`, {
deployment: deploymentV1,
stageName: 'v1'
});

// Create resources and methods for v1
const postsResourcesV1 = apiGateway.root.addResource("posts");
postsResourcesV1.addMethod("POST", props.createPost);

const postResourcesV1 = postsResourcesV1.addResource("{id}");
postResourcesV1.addMethod("GET", props.getPost);
postResourcesV1.addMethod("DELETE", props.testLambda);
}
}
```

And this is my `Launcher.ts` file:

```typescript
import { App } from "aws-cdk-lib"
import { NetworkStack } from "./stacks/NetworkStack";
import { AppConfig } from "./config/types";
import { loadConfig } from "./config/loadConfig";
import { DataStack } from "./stacks/DataStack";
import { LambdaStack } from "./stacks/LambdaStack";
import { ApiGatewayStack } from "./stacks/ApiGatewayStack";
import { CertificateStack } from "./stacks/CertificateStack";
import { Route53Stack } from "./stacks/Route53Stack";
import { ApiGatewayDomain } from "aws-cdk-lib/aws-route53-targets";
import { SecurityStack } from "./stacks/SecurityStack";

const app = new App();

const appConfig: AppConfig = loadConfig(app);

const route53Stack = new Route53Stack(app, `ButlaiRoute53Stack-${appConfig.ENV}`, {
config: appConfig,
})

const certificateStack = new CertificateStack(app, `ButlaiCertificateStack-${appConfig.ENV}`, {
config: appConfig,
hostedZone: route53Stack.hostedZone
});

const networkStack = new NetworkStack(app, `ButlaiNetworkStack-${appConfig.ENV}`, {
config: appConfig
});

const securityStack = new SecurityStack(app, `ButlaiSecurityStack-${appConfig.ENV}`, {
vpc: networkStack.vpc,
});

const dataStack = new DataStack(app, `ButlaiDataStack-${appConfig.ENV}`, {
config: appConfig,
vpc: networkStack.vpc,
databaseSecurityGroup: securityStack.databaseSecurityGroup,
});

const lambdaStack = new LambdaStack(app, `ButlaiLambdaStack-${appConfig.ENV}`, {
config: appConfig,
vpc: networkStack.vpc,
databaseSecrets: dataStack.databaseSecrets,
lambdaSecurityGroup: securityStack.lambdaSecurityGroup,
databaseSecurityGroup: securityStack.databaseSecurityGroup,
});

const apiGatewayStack = new ApiGatewayStack(app, `ButlaiApiGatewayStack-${appConfig.ENV}`, {
config: appConfig,
hostedZone: route53Stack.hostedZone,
certificate: certificateStack.certificate,
testLambda: lambdaStack.testLambdaFunction,
createPost: lambdaStack.createPostLambdaFunction,
getPost: lambdaStack.getPostLambdaFunction,
});

```

And this is what I try to do:
```typescript
// postResourcesV1.addMethod("DELETE", props.testLambda);
```

this results in the following error in the Console:

The CloudFormation Console for this stack tells me this:
**Export ButlaiLambdaStack-dev:ExportsOutputFnGetAtttestFunctionFOOBAR cannot be deleted as it is in use by ButlaiApiGatewayStack-dev**

But there aren't any other references to that testLambda function elsewhere in my codebase. Next to that, I'm not trying to DELETE the whole Lambda function, I want to deploy a new version of the API without that Method.

### Expected Behavior

In the next deployment (that I'm trying to deploy), the method that I want to delete from the API Gateway should be removed.
The Lambda function itself will still exist in AWS, in case we want to revert to an older deployment version.

### Current Behavior

The current behaviour is a ROLLBACK.
Nothing else happens, the stack won't be updated, the method still exists and is callable.

### Reproduction Steps

If you would copy and paste the code that I posted above (the ApiGatewayStack). And deploy it using:
`cdk deploy --all`
Then, comment out one of the added Lambda Functions an re-run:
`cdk deploy --all`

### Possible Solution

_No response_

### Additional Information/Context

_No response_

### CDK CLI Version

2.147.0 (build 3338fc0)

### Framework Version

_No response_

### Node.js Version

v22.2.0

### OS

Mac OS 14.5 (23F79)

### Language

TypeScript

### Language Version

TypeScript (5.4.3)

### Other information

_No response_

Contributor guide

Open the contributing guide

Research direction

Start with the ApiGatewayStack and Launcher.ts examples, then reproduce the behavior with cdk deploy --all after commenting out postResourcesV1.addMethod("DELETE", props.testLambda). Done means the API Gateway method is removed on deployment while the Lambda function remains available and the stacks do not roll back.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, typescript
Domain
api, cloud, infrastructure
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.