Skip to content

fix: handle unscheduled Lambda runtime block dates - #4945

Merged
kddejong merged 1 commit into
aws-cloudformation:mainfrom
kddejong:fix/issue/4944
Oct 27, 2026
Merged

kddejong merged 1 commit into
aws-cloudformation:mainfrom
kddejong:fix/issue/4944

Conversation

@kddejong

Copy link
Copy Markdown
Contributor

Fixes #4944

Problem

LmbdRuntimeLifecycle.json permits create-block and update-block to be null, which is how AWS publishes a runtime whose deprecation date is announced but whose block dates are not yet scheduled. All three rules that read the file called datetime.strptime on those values with no null guard, so such a runtime raised instead of being validated.

dotnet9 is the only entry in that state today ({"create-block": null, "deprecated": "2026-11-10", "successor": "dotnet10", "update-block": null}), matching the Lambda runtimes page, which shows "Not scheduled" for both block columns. The data is correct — AWS announces the deprecation date first and the block dates later, so every runtime passes through this state.

Reproduced on main at 027bdd1b9:

E1101 Exception 'strptime() argument 1 must be str, not None' raised while validating 'cfnLint'
template.yaml:5:7

E2531 and E2533 raise today. W2531 survives only because and short-circuits on the deprecation comparison, which is still false. With the clock frozen the way the rules' own tests do it:

2026-10-27  W2531 -> 0 error(s)
2026-11-10  W2531 -> RAISES TypeError: strptime() argument 1 must be str, not None

So W2531 joins the other two on 2026-11-10.

Fix

A null block date now means "not yet scheduled" rather than being parsed as a date. Each date is handled independently, since AWS can schedule one before the other.

Rule Before After
W2531 deprecated <= today and create-block > today and update-block > today same, but a null block date satisfies its clause — so the warning fires on the deprecation date alone while blocking is unscheduled
E2531 create-block <= today and update-block > today silent while create-block is null; a null update-block satisfies the second clause (creates blocked, updates not)
E2533 update-block <= today silent while update-block is null

E2531 and E2533 staying silent is deliberate: CloudFormation is not refusing the operation yet, so an error would be a false positive. W2531 firing is the finding users want in that state — the runtime is deprecated even though AWS has not said when creates get blocked.

Message

The shared message interpolated both block dates, which rendered as Creation was disabled on None and update on None. The three rules now build it through one helper that varies only the middle clause:

State Clause
both scheduled Creation was disabled on 'C' and update on 'U'. (unchanged, byte-identical)
update unscheduled Creation was disabled on 'C' and update blocking is not yet scheduled.
creation unscheduled Creation blocking is not yet scheduled and update was disabled on 'U'.
neither scheduled Creation and update blocking are not yet scheduled.

The both-scheduled string is byte-identical to the old one on purpose, because four quickstart snapshot fixtures and the existing unit tests assert it. No snapshot needed regenerating.

Frozen-clock output after the fix:

2026-10-27  W2531 -> 0 error(s)          E2531 -> 0 error(s)   E2533 -> 0 error(s)
2026-11-10  W2531 -> 1 error(s)          E2531 -> 0 error(s)   E2533 -> 0 error(s)
            Runtime 'dotnet9' was deprecated on '2026-11-10'. Creation and update
            blocking are not yet scheduled. Please consider updating to 'dotnet10'

Verification

  • cfn-lint -t on the issue's template: no E1101. (dotnet9 still draws E3030 because it is absent from the Runtime enum — a schema gap belonging in resource-provider-enhanced-schemas, noted in the issue.)
  • Exhaustive equivalence check: every one of the 47 lifecycle entries, evaluated against all three rules at every date in the file ±1 day (4,539 findings on main). Every single difference is on dotnet9; no other runtime changed its result in any way.
  • Good-fixture sweep byte-identical to main: cfn-lint -t "test/fixtures/templates/good/**/*.yaml", diffed against the same command run from a pristine upstream/main worktree.
  • Quickstart integration tests and the three rule test files: 231 passed, and git status test/fixtures/results/ is clean.
  • Full suite: 9 failed, 3235 passed, the identical 9 failures by test ID as a pristine upstream/main run of the same suite in the same checkout (9 failed, 3220 passed). All 9 are missing optional dependencies (pydot, junit, sarif) and the pricing-API tests. The +15 are the new cases.
  • pre-commit run --all-files: ruff, ruff-format, isort, bandit and mypy all pass.

Tests

Five cases per rule, covering a null-block entry before and after its deprecation date and both half-scheduled permutations. They use an injected synthetic entry rather than the real dotnet9 row, so they keep testing the code path after AWS schedules dotnet9's block dates and the data file is updated.

11 of the 15 new cases fail against pre-fix code with the reported TypeError; the other 4 pass there only because short-circuiting never reaches the null.

Not included

nodejs26.x and python3.15 are currently omitted from LmbdRuntimeLifecycle.json to dodge this crash. With it fixed they could be carried, and unlike dotnet9 both are in the Runtime enum — so adding them would change live behaviour for real templates. That is a data decision, left to the maintainer. LmbdRuntimeLifecycle.json is untouched here.

E2531, E2533 and W2531 called datetime.strptime on create-block and
update-block without a null guard, so a runtime whose deprecation date is
announced before its block dates are scheduled raised instead of being
validated. A null block date now means 'not yet scheduled': W2531 fires on
the deprecation date alone, and E2531 and E2533 stay silent until their own
block date is both scheduled and reached.

Fixes aws-cloudformation#4944
@codecov

codecov Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.69%. Comparing base (027bdd1) to head (3034634).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4945   +/-   ##
=======================================
  Coverage   94.68%   94.69%           
=======================================
  Files         441      442    +1     
  Lines       16058    16083   +25     
  Branches     3114     3119    +5     
=======================================
+ Hits        15204    15229   +25     
  Misses        470      470           
  Partials      384      384           
Flag Coverage Δ
unittests 94.68% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@kddejong
kddejong marked this pull request as ready for review October 27, 2026 20:38
@kddejong
kddejong merged commit bd8db79 into aws-cloudformation:main Oct 27, 2026
42 of 46 checks passed
@kddejong
kddejong deleted the fix/issue/4944 branch October 27, 2026 20:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

E2531, E2533 and W2531 crash on a runtime whose block dates are not yet scheduled

1 participant