aws / aws/aws-cdk

core: acknowledgeWarning() before addWarningV2() on the same construct does not suppress the warning

Open Beginner friendly
#38,820 0 comments 0 reactions 0 assignees View on GitHub
@aws-cdk/core needs-triage
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

### Describe the bug

`Annotations.of(scope).acknowledgeWarning(id)` is documented as subtree-scoped ("The acknowledgement will apply to all child scopes"). However, if you acknowledge a warning on a construct **before** a warning with that same id is emitted on the **same** construct, the acknowledgement is ignored and the warning is still emitted.

The reverse order (emit first, then acknowledge) works, and acknowledging on an **ancestor** works for descendants in either order. Only the "acknowledge-then-emit on the same construct" case is broken. `acknowledgeInfo()` / `addInfoV2()` share the same lookup and have the same bug.

### Expected Behavior

Acknowledging a warning id on construct `C` suppresses a later `addWarningV2` with that id emitted on `C` itself (consistent with the documented subtree semantics and with the ancestor/child cases).

### Current Behavior

The warning is emitted anyway. Synthesizing the app below yields a warning on `/S1/C1`:

```
[ { path: '/S1/C1', message: 'You should know this! [ack: MESSAGE]' } ]
```

### Reproduction Steps

```ts
import { App, Stack } from 'aws-cdk-lib';
import { Annotations } from 'aws-cdk-lib';
import { Construct } from 'constructs';

const app = new App();
const stack = new Stack(app, 'S1');
const c1 = new Construct(stack, 'C1');

// Acknowledge FIRST, then emit on the SAME construct
Annotations.of(c1).acknowledgeWarning('MESSAGE', 'ack');
Annotations.of(c1).addWarningV2('MESSAGE', 'You should know this!');

app.synth(); // warning is still present on /S1/C1 (expected: suppressed)
```

### Root Cause

In `packages/aws-cdk-lib/core/lib/annotations.ts`, the private `Acknowledgements.searchPaths()` is documented as returning the node's own full path plus its ancestor prefixes (`Given 'a/b/c', return ['a/b/c', 'a/b', 'a']`), but the loop only pushes a prefix when it finds a `/`, so the final segment — the construct's **own** full path — is never included. It actually returns `['a/b', 'a']`.

`Acknowledgements.add()` records the ack under the construct's exact path, while `addWarningV2` gates emission on `has()`, which only checks the paths from `searchPaths()`. Because the construct's own path is excluded, the ack recorded on `C` is invisible to a warning emitted on `C`. Emitting on a **child** works because the child's `searchPaths()` includes `C` as an ancestor; the emit-then-ack order works because `acknowledgeWarning` also calls the self-inclusive `removeWarningDeep()`.

### Possible Solution

Make `searchPaths()` include the node's own full path (matching its docstring). Fix + regression tests in progress.

### Environment

- **CDK CLI Version:** n/a (framework behavior, reproduced against `main`)
- **Framework Version:** aws-cdk-lib (main)
- **Node.js Version:** n/a
- **OS:** n/a
- **Language:** TypeScript

### This is 🐛 Bug Report

Contributor guide

Open the contributing guide

Research direction

Start in packages/aws-cdk-lib/core/lib/annotations.ts and read Acknowledgements.searchPaths(), then trace how addWarningV2() uses has(). Add regression coverage for acknowledging before emitting on the same construct, including the related info path, and confirm synthesis produces no warning for the acknowledged id.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
cloud
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
75/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.