aws / aws/aws-cdk

(APIGatewayV2): API Gateway V2 ALB Integration - Multiple Route Creation Failure

Open
#35,004 2 comments 0 reactions 0 assignees View on GitHub
@aws-cdk/aws-apigatewayv2 feature-request p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

### Describe the bug

Hey!

I'm not sure if this is a bug or if I'm misunderstanding something.
Posted to [discussions](https://github.com/aws/aws-cdk/discussions/34666) too, but I did not get any replies, so I created an issue.

I have a routes array (100+ items in it), which contains all routes for my service, but whenever I'm trying to deploy this solution, it will fail with the following error:

```
Unable to retrieve listener port and load balancer DNS name from ELB listener arn [listener-arn]. Please check that ELB listener exists in account [account-id]
```

However, when I only want to deploy, say, 50 routes (not every route at once), it works just fine.

### Regression Issue

- [ ] Select this option if this issue appears to be a regression.

### Last Known Working CDK Library Version

_No response_

### Expected Behavior

It should create all routes correctly without throwing the error:
```
Unable to retrieve listener port and load balancer DNS name from ELB listener arn [listener-arn]. Please check that ELB listener exists in account [account-id]
```

### Current Behavior

It throws
```
Unable to retrieve listener port and load balancer DNS name from ELB listener arn [listener-arn]. Please check that ELB listener exists in account [account-id]
```
but the listener exists, so the error does not make any sense to me.

### Reproduction Steps

```typescript
import * as apigw from 'aws-cdk-lib/aws-apigatewayv2';
import * as apigwInt from 'aws-cdk-lib/aws-apigatewayv2-integrations';
import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
import { Construct } from 'constructs';

class ApiGatewayWithAlbIntegration extends Construct {
constructor(scope: Construct, id: string) {
super(scope, id);

// Create or import ALB listener
const listener = elbv2.ApplicationListener.fromLookup(this, 'Listener', {
listenerArn: 'arn:aws:elasticloadbalancing:region:account:listener/app/alb/id/id'
});

// Create VPC Link
const vpcLink = new apigw.VpcLink(this, 'VpcLink', {
vpc: vpc
});

// Create HTTP API
const api = new apigw.HttpApi(this, 'Api');

// This works - single route with proxy
const proxyParameterMapping = new apigw.ParameterMapping()
.appendHeader('custom-header', apigw.MappingValue.custom('value'))
.overwritePath(apigw.MappingValue.custom('/$request.path.proxy'));

new apigw.HttpRoute(this, 'ProxyRoute', {
httpApi: api,
routeKey: apigw.HttpRouteKey.with('/{proxy+}', apigw.HttpMethod.ANY),
integration: new apigwInt.HttpAlbIntegration('Integration', listener, {
vpcLink,
parameterMapping: proxyParameterMapping
})
});

// This fails - multiple routes in sequence
const routes = [
{ path: '/users', method: apigw.HttpMethod.GET, backendPath: '/api/v1/users' },
{ path: '/users', method: apigw.HttpMethod.POST, backendPath: '/api/v1/users' },
{ path: '/products', method: apigw.HttpMethod.GET, backendPath: '/api/v1/products' },
// ... more routes
];

for (const route of routes) {
// Each route needs its own parameter mapping to forward the correct path
const routeParameterMapping = new apigw.ParameterMapping()
.appendHeader('custom-header', apigw.MappingValue.custom('value'))
.overwritePath(apigw.MappingValue.custom(route.backendPath)); // This is crucial

new apigw.HttpRoute(this, `Route-${route.path}-${route.method}`, {
httpApi: api,
routeKey: apigw.HttpRouteKey.with(route.path, route.method),
integration: new apigwInt.HttpAlbIntegration(
`Integration-${route.path}-${route.method}`,
listener,
{
vpcLink,
parameterMapping: routeParameterMapping,
method: route.method
}
)
});
}
}
}
```

### Possible Solution

- So, deploying in multiple steps is working, but far from ideal.
- The listener exists, so the error does not make any sense to me
- Is this a known limitation with the ALB listener? Or am I throttling the API to retrieve the listener when the HttpAlbIntegration is created?
- Are there best practices for creating multiple routes with ALB integrations that I'm not aware of?

Versions:
- "aws-cdk": "^2.1013.0"
- "aws-cdk-lib": "^2.194.0"
- "constructs": "^10.4.2"

### Additional Information/Context

- I cannot use `{proxy+}` since I have other routes that should not be accessible via this gateway for my service, so I have to specify which exact routes users can access
- I must have different parameter mappings for each route
- Currently, I'm using `{proxy+}` with an authorizer lambda, which just checks the route and forwards it to the service whenever needed, but I thought I didn't need the authorizer lambda for this after all.

### AWS CDK Library version (aws-cdk-lib)

2.194.0

### AWS CDK CLI version

2.1013.0

### Node.js Version

22

### OS

MacOS 15.4.1

### Language

TypeScript

### Language Version

_No response_

### Other information

_No response_

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the failure with the provided TypeScript example using HttpAlbIntegration, HttpRoute, and ApplicationListener.fromLookup, comparing one route with 100+ routes. Trace how the ALB listener is retrieved while integrations are created; done means deploying all routes successfully without the listener error while retaining each route's parameter mapping.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, typescript
Domain
api, cloud
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.