Found by the code review of PR #1439 (the table-level sibling of this class).
DynamoDBGlobalTableProvider's per-GSI on-demand reset — the #1423 fix — decides
"the template dropped this member" from whether the value COERCED, not from
whether the key is present:
const maxWrite = toFiniteNumber(
asRecord(gsi['WriteOnDemandThroughputSettings'])?.['MaxWriteRequestUnits']
);
...
if (previousOnDemand.MaxWriteRequestUnits !== undefined &&
onDemand.MaxWriteRequestUnits === undefined) {
onDemand.MaxWriteRequestUnits = ON_DEMAND_LIMIT_RESET; // -1
}
toFiniteNumber returns undefined for a present-but-unparseable value — an
unresolved intrinsic ({Ref: ...}), an empty string, an object. Such a GSI
therefore falls into the reset branch and is sent -1, which silently CLEARS
the ceiling the template was trying to set.
That is the same silent-wrong-action class the reset exists to remove: the user
asked for a value, and cdkd answered by deleting the setting, with the deploy
reporting success.
Why PR #1439 did not fix it here
The identical hazard existed in that PR's own table-level code and was caught in
self-review; the table-level gate now tests RAW key presence
(rawMaxWrite !== undefined) and leaves the coercion untouched, so an
unresolvable value still reaches AWS and fails loudly.
Applying the same shape per-GSI is more invasive: the modified loop iterates
the SDK-TRANSLATED index shapes, so the raw CFn blob for that index (and the
matching local-replica entry, where the read half lives) has to be threaded in
or re-looked-up by IndexName before the presence test can be made. That is
surgery on #1423's shipped logic rather than a one-line gate change, and #1439
was already carrying a live-probe cycle plus a real-AWS integ.
Fix
In the per-GSI modified loop, gate each member's reset on the RAW CFn key
being ABSENT:
- write half:
GlobalSecondaryIndexes[?IndexName==X].WriteOnDemandThroughputSettings.MaxWriteRequestUnits
- read half:
Replicas[local].GlobalSecondaryIndexes[?IndexName==X].ReadOnDemandThroughputSettings.MaxReadRequestUnits
(with the GSI-level spelling as the documented fallback)
Keep the existing coercion for the present case so an unresolvable value still
surfaces as an AWS-side error.
Tests
Mirror the table-level regression test added in #1439 — a per-GSI
MaxWriteRequestUnits: { Ref: 'SomeUnresolvedParameter' } must NOT produce
-1, and must still forward the value.
Found by the code review of PR #1439 (the table-level sibling of this class).
DynamoDBGlobalTableProvider's per-GSI on-demand reset — the #1423 fix — decides"the template dropped this member" from whether the value COERCED, not from
whether the key is present:
toFiniteNumberreturnsundefinedfor a present-but-unparseable value — anunresolved intrinsic (
{Ref: ...}), an empty string, an object. Such a GSItherefore falls into the reset branch and is sent
-1, which silently CLEARSthe ceiling the template was trying to set.
That is the same silent-wrong-action class the reset exists to remove: the user
asked for a value, and cdkd answered by deleting the setting, with the deploy
reporting success.
Why PR #1439 did not fix it here
The identical hazard existed in that PR's own table-level code and was caught in
self-review; the table-level gate now tests RAW key presence
(
rawMaxWrite !== undefined) and leaves the coercion untouched, so anunresolvable value still reaches AWS and fails loudly.
Applying the same shape per-GSI is more invasive: the
modifiedloop iteratesthe SDK-TRANSLATED index shapes, so the raw CFn blob for that index (and the
matching local-replica entry, where the read half lives) has to be threaded in
or re-looked-up by
IndexNamebefore the presence test can be made. That issurgery on #1423's shipped logic rather than a one-line gate change, and #1439
was already carrying a live-probe cycle plus a real-AWS integ.
Fix
In the per-GSI
modifiedloop, gate each member's reset on the RAW CFn keybeing ABSENT:
GlobalSecondaryIndexes[?IndexName==X].WriteOnDemandThroughputSettings.MaxWriteRequestUnitsReplicas[local].GlobalSecondaryIndexes[?IndexName==X].ReadOnDemandThroughputSettings.MaxReadRequestUnits(with the GSI-level spelling as the documented fallback)
Keep the existing coercion for the present case so an unresolvable value still
surfaces as an AWS-side error.
Tests
Mirror the table-level regression test added in #1439 — a per-GSI
MaxWriteRequestUnits: { Ref: 'SomeUnresolvedParameter' }must NOT produce-1, and must still forward the value.