What it means
Provisioned concurrency keeps a number of execution environments initialised and waiting, so invocations skip the cold start entirely. Those environments are built from a specific version of your code — they have already imported the modules and run everything at module scope, which is the whole point.
Weighted alias routing does something incompatible with that. It makes an alias resolve to two versions at once, splitting traffic between them by weight, which is how canary and linear deployments shift load gradually. An alias configured that way has no single version for pre-initialised environments to be built from.
So Lambda refuses the combination on the same alias, in either order: adding routing to an alias that has capacity, or adding capacity to an alias that has routing. The message is the same and the conflict is the same.
The resolution is to attach capacity at a level where there is no ambiguity — the version rather than the alias. Versions are immutable and singular, so provisioned concurrency on version 8 and on version 9 is unambiguous, and the alias above them is then free to shift weights between two already-warm targets. That is also the configuration you want during a canary: the new version is warm before it takes any traffic, rather than cold-starting under a share of production load.
The cost is worth stating plainly, because it is the part that surprises people. During the shift you are paying for provisioned capacity on both versions. That is unavoidable if you want warm capacity throughout a gradual rollout, and it makes releasing the old version's capacity promptly after the shift completes a real line item rather than housekeeping.
Where you'll see it
Deployment output
Not in CloudWatchThis failure happens before the function runs, so nothing about it reaches CloudWatch Logs — there is no invocation, and no log group entry to find. Once the deployment succeeds and the function starts running, the rest of this index covers what you will see there.
Causes, most likely first
The alias already has provisioned concurrency and you added routing
Check whether the alias has a provisioned-concurrency configuration before the routing change. Capacity is allocated to the version the alias resolves to; introducing a second version makes that allocation ambiguous, so the routing change is refused.
The alias already has weighted routing and you added provisioned concurrency
Read the alias's RoutingConfig. The same conflict from the other direction — Lambda cannot decide which of the two versions the capacity belongs to.
A canary deployment is trying to do both at once
Look at how the deployment tool is configured. CodeDeploy canary and linear strategies work by shifting alias weights, so combining one with provisioned concurrency on the same alias runs into this by construction.
Fixes
Put provisioned concurrency on the version, not the alias
Configuring capacity against a specific version leaves the alias free to shift weights, which is what makes gradual deployment and warm capacity coexist. Provision both versions during the shift, then release the old one.
bash# Capacity on the versions themselves...
aws lambda put-provisioned-concurrency-config \
--function-name checkout-fn --qualifier 8 \
--provisioned-concurrent-executions 20
aws lambda put-provisioned-concurrency-config \
--function-name checkout-fn --qualifier 9 \
--provisioned-concurrent-executions 20
# ...leaving the alias free to shift traffic between them.
aws lambda update-alias --function-name checkout-fn --name live \
--function-version 8 --routing-config 'AdditionalVersionWeights={"9"=0.1}'
Remove the routing configuration before changing capacity
Where the shift is finished, clearing the weights returns the alias to a single version and lets provisioned concurrency be attached to it again.
bashaws lambda update-alias \
--function-name checkout-fn --name live \
--function-version 9 --routing-config 'AdditionalVersionWeights={}'
Budget for both versions during a shift
Provisioning two versions simultaneously means paying for both for the duration of the deployment. That is the real cost of combining warm capacity with gradual rollout, and it is worth planning rather than discovering — release the old version's capacity as soon as the shift completes.
Also seen as
The same underlying failure, worded differently by a different runtime, SDK version, or logging layer. All of these land here — there is no separate page for each phrasing.
Related errors
Errors that show up alongside this one, or that people mistake for it.
References
- AWS Lambda Developer Guide — Configuring provisioned concurrency
- AWS Lambda Developer Guide — Lambda function aliases
This one happens before there are any logs.
LogStitch reads CloudWatch, and a deployment that fails never writes to it — so this is not an error it can find for you. Once the function deploys and starts running, the free web stitcher groups its invocations in your browser, and the Mac app does the same across every function in your account.