(aws-autoscaling): StepScalingPolicy emits spurious cooldown deprecation warning even when cooldown is not specified
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 74
Description
### Describe the bug
Every `StepScalingPolicy` (and therefore every call to `AutoScalingGroup.scaleOnMetric`) emits a `StepScalingActionProps#cooldown` deprecation warning during synthesis, even
when the user never sets `cooldown`. Each `StepScalingPolicy` creates two `StepScalingAction` instances (upper and lower), so one `scaleOnMetric` call produces two warnings.
In a stack with many step-scaled ASGs, this pollutes build output and drowns out legitimate deprecation signals.
The root cause is a mismatch between the generated JSII deprecation checker and the L2 construct code. The checker uses `'cooldown' in p` (a key-existence check) rather than
`p.cooldown !== undefined` (a value check). Because `StepScalingPolicy` unconditionally includes `cooldown: props.cooldown` in the props object literal it passes to
`StepScalingAction` — even when `props.cooldown` is `undefined` — the key is always present and the warning fires unconditionally.
This is analogous to #37818 (`CfnAutoScalingGroup#notificationConfiguration`), but the mechanism differs slightly: #37818 involves an L1 `cfnProperties` getter reading
through a deprecated public getter, whereas this issue involves a props object literal that always includes the deprecated key.
### Regression Issue
- [ ] Select this option if this issue appears to be a regression.
### Last Known Working CDK Library Version
_No response_
### Expected Behavior
When a user does not set `cooldown` on `scaleOnMetric` (or otherwise on `BasicStepScalingPolicyProps`), no deprecation warning should be emitted.
Deprecation warnings should only fire when a user *actually passes* the deprecated property.
### Current Behavior
Two deprecation warnings are printed per `StepScalingPolicy` per synthesis (one each for the upper and lower `StepScalingAction`), regardless of whether `cooldown` is ever
assigned.
Exact warning text (verbatim, 3 lines, no stack trace):
```
[WARNING] aws-cdk-lib.aws_autoscaling.StepScalingActionProps#cooldown is deprecated.
cooldown is not valid with step scaling action
This API will be removed in the next major release.
```
### Reproduction Steps
### Reproduction Steps
Minimal reproduction (TypeScript):
```typescript
import * as cdk from 'aws-cdk-lib';
import * as autoscaling from 'aws-cdk-lib/aws-autoscaling';
import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
const app = new cdk.App();
const stack = new cdk.Stack(app, 'ReproStack');
const vpc = new ec2.Vpc(stack, 'Vpc');
const asg = new autoscaling.AutoScalingGroup(stack, 'Asg', {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MICRO),
machineImage: ec2.MachineImage.latestAmazonLinux2(),
});
// No `cooldown` is passed here.
asg.scaleOnMetric('StepPolicy', {
metric: new cloudwatch.Metric({ namespace: 'Test', metricName: 'M' }),
scalingSteps: [
{ upper: 10, change: -1 },
{ lower: 50, change: +1 },
],
adjustmentType: autoscaling.AdjustmentType.CHANGE_IN_CAPACITY,
});
app.synth();
Run cdk synth. Two deprecation warnings for StepScalingActionProps#cooldown are printed, even though the user code never touches that property.
### Possible Solution
Two possible fixes:
1. In aws-cdk-lib/aws-autoscaling/lib/step-scaling-policy.ts, conditionally include cooldown in the StepScalingAction props object only when props.cooldown !== undefined.
For example, spread it conditionally: ...(props.cooldown !== undefined ? { cooldown: props.cooldown } : {}).
2. In the generated JSII deprecation checker, change the key-existence check 'cooldown' in p to a value check p.cooldown !== undefined. This would also fix any other X in p
checks on deprecated optional props across the library.
Option 2 is the broader fix and would prevent similar issues for other deprecated optional properties.
### Additional Information/Context
In the generated aws-cdk-lib/aws-autoscaling/lib/step-scaling-policy.js, StepScalingPolicy constructs its upper and lower actions by passing a props object literal that
unconditionally includes the deprecated cooldown key:
```
this.lowerAction = new StepScalingAction(this, 'LowerPolicy', {
adjustmentType,
cooldown: props.cooldown, // ← always included, even when undefined
estimatedInstanceWarmup: props.estimatedInstanceWarmup,
metricAggregationType: props.metricAggregationType ?? aggregationTypeFromMetric(props.metric),
minAdjustmentMagnitude: props.minAdjustmentMagnitude,
autoScalingGroup: props.autoScalingGroup,
});
(The same pattern is used for this.upperAction.)
StepScalingAction's constructor invokes the JSII deprecation checker on its props:
class StepScalingAction extends Construct {
constructor(scope, id, props) {
super(scope, id);
try {
jsiiDeprecationWarnings.aws_cdk_lib_aws_autoscaling_StepScalingActionProps(props);
} catch (error) { /* rethrow */ }
// ...
}
}
The generated checker in aws-cdk-lib/.warnings.jsii.js uses a key-existence test:
function aws_cdk_lib_aws_autoscaling_StepScalingActionProps(p) {
if (p != null) {
// ...
'cooldown' in p && print(
'aws-cdk-lib.aws_autoscaling.StepScalingActionProps#cooldown',
'cooldown is not valid with step scaling action'
);
// ...
}
}
```
Because 'cooldown' in p is true whenever the key is present (regardless of value), and StepScalingPolicy always includes the key, the warning is emitted on every StepScalingPolicy construction. The public L2 surface (BasicStepScalingPolicyProps) is innocent — users never need to pass cooldown to trigger the warning.
### AWS CDK Library version (aws-cdk-lib)
aws-cdk-lib@2.245.0
### AWS CDK CLI version
2.1114.1
### Node.js Version
v24.14.0
### OS
AL2023 (kernel 6.12.80)
### Language
TypeScript
### Language Version
5.9.3
### Other information
Similar to https://github.com/aws/aws-cdk/issues/37818
Contributor guide
Research direction
Start with aws-cdk-lib/aws-autoscaling/lib/step-scaling-policy.ts and inspect how the upper and lower StepScalingAction props are assembled, then compare the behavior with aws-cdk-lib/.warnings.jsii.js. Run the TypeScript reproduction with cdk synth; done means omitting cooldown produces no warning while explicitly passing it still reports the deprecation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cloud, infrastructure
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100