Skip to content

feat(cli): send telemetry from a detached subprocess to unblock CLI exit - #1779

Merged
sanjanaravikumar-az merged 35 commits into
mainfrom
sanjrkmr/telemetry-subprocess
Sep 23, 2026
Merged

sanjanaravikumar-az merged 35 commits into
mainfrom
sanjrkmr/telemetry-subprocess

Conversation

@sanjanaravikumar-az

@sanjanaravikumar-az sanjanaravikumar-az commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

This PR removes the telemetry request from the CLI's critical path. The CLI posts telemetry at the end of every invocation. That POST is 3–4 round trips to an HTTPS endpoint, and at ~100ms+ latency it adds meaningful time to
every cdk command — for a fire-and-forget send nobody is waiting on. This moves the POST into a detached child process: the CLI writes the payload and exits immediately, and the child delivers the telemetry on its own and outlives the parent.

How it works

  • A dedicated bundled entry point (sender-bundle.js) is spawned detached and unref'd. It reuses the real proxy-agent, so proxy / PAC / SOCKS / NO_PROXY behaviour matches the rest of the CLI.
  • The parent hands the batch off via a file. The proxy URL and the CA bundle path (not the certificate bytes) are passed as plain data, since an Agent can't cross a process boundary. Forwarding the path also keeps payload size independent of CA-bundle size.
  • Delivery is fire-and-forget: the CLI never learns whether the POST succeeded.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

Roko AI Agent added 3 commits July 28, 2026 20:06
The telemetry POST at the end of every CLI invocation was awaited before the
process could exit, adding ~300ms to every command.

Hand the payload to a detached child process instead. bin/cdk re-invokes itself
with CDK_TELEMETRY_SENDER=1 and dispatches to a new builtins-only sender module
before requiring the CLI bundle (which costs ~600ms to load), so the child stays
cheap. The parent writes the batch to the child's stdin, unrefs it, and exits.

Because the published package has zero runtime dependencies, the sender can only
use Node built-ins. That rules out proxy-agent, so it re-implements the parts we
actually support: HTTP CONNECT tunnelling through http:// and https:// proxies,
Basic proxy auth, a forwarded CA bundle, and proxy-from-env's NO_PROXY
semantics. SOCKS and PAC proxies fail closed (telemetry is skipped rather than
bypassing a proxy that is usually mandatory).

Refs D488314716
Adds unit coverage for the bin/cdk path resolution, and two integration tests:
one asserting the CLI's exit time no longer tracks the telemetry endpoint (the
endpoint is a TCP black hole that never responds), and one proving delivery still
works for proxy users, reusing the existing TLS-terminating mockttp harness.

Also applies eslint --fix (import ordering and brace newlines).
… byte-accurate stdin cap, drop blocking connectivity check)

The legacy 'Telemetry Sent Successfully' trace was retained verbatim so the
existing integration tests kept passing, but it is now a lie: the parent only
hands the batch to a detached sender and never learns whether the POST
succeeded. Replace it with a single 'Telemetry dispatched (pid N, M bytes)'
line, hoist the stable 'Telemetry dispatched' prefix into a named constant so
it is obvious it must not change casually, and update all seven integration
tests plus the unit test that matched the old string.

The sender's stdin cap was compared against a string's length, which counts
UTF-16 code units, so a multi-byte payload could reach three times the intended
size. Read stdin as Buffers, measure with byteLength, and decode once at the
end -- which also removes the need to reason about multi-byte sequences that
straddle a chunk boundary. Extracted as readAll() so the cap is directly
testable.

Finally, drop the NetworkDetector connectivity gate. Checking reachability
before dispatching is itself a network call on the CLI's exit path -- up to a
3s HEAD request on a cold cache -- which is exactly what this sink exists to
avoid. Offline machines now spawn a child that fails and exits; it has its own
timeouts and swallows every error, so being wrong costs one short-lived
process. This leaves the sink's 'agent' prop unused (the child receives proxy
configuration as proxyUrl/caCert, not as an Agent), so remove that plumbing
too. The notices path still uses NetworkDetector and is untouched.

Refs D488314716
@github-actions

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@aws-cdk-automation
aws-cdk-automation requested a review from a team July 29, 2026 17:57
…ot the cert

The detached sender was written against Node built-ins only, which meant
hand-rolling an HTTP CONNECT tunnel, a TLS upgrade, an HTTP/1.1 framer and a
copy of proxy-from-env. That constraint was self-imposed: the child is detached
and nobody waits on its load time, so it does not need to be small. Make it a
proper esbuild entry point instead and let it use the real proxy-agent. SOCKS
and PAC proxies work again as a result -- the hand-rolled version had to skip
those users rather than risk bypassing a mandatory proxy.

Also fixes a bug that silently cost every corporate-proxy user all of their
telemetry: the sink forwarded the CA bundle CONTENTS in the payload and measured
the whole payload against a 64KB cap. A system CA bundle is around 190KB, so
those invocations were over the cap and dropped, every single time. Forward the
absolute path instead and let the child read it -- which ProxyAgentProvider
already knows how to do.

The payload now travels in a temp file whose path is passed in argv rather than
down the child's stdin, so there is no reason to cap it at all: stdin was only
capped because writing more than a pipe buffer's worth would have blocked the
exit this whole change exists to avoid.

Other cleanups that fall out of the above:

- EndpointTelemetrySink goes back to POSTing to the endpoint, as it does on
  main; the new SubprocessTelemetrySink owns the spawning. The POST itself is
  shared between them.
- bin/cdk is back to its original three lines. It no longer publishes its own
  path in CDK_CLI_BIN_PATH or re-executes itself as a sender, so cli-bin-path.ts
  is gone too -- the sender is resolved from the package root directly.
- ToolkitError is imported from its defining module rather than the toolkit-lib
  barrel. Via the barrel, esbuild pulled the entire toolkit into the sender
  bundle: 11.5MB for one error class, versus 1.9MB without it.
Handing the batch to a detached child means nothing in this process ever
learns whether the POST worked. That was the one genuinely uncomfortable
part of the design, so give it a way to be measured: the child writes
{ok, statusCode, reason, at} to telemetry-last-send.json under CDK_HOME,
and the next invocation reads it and reports counters.previousSendFailed
on its first event. Only failures are reported -- a counter present on
nearly every event tells you nothing -- and the file is consumed on read,
so one failure is reported once rather than forever. It gets its own file
rather than joining telemetry-state.json because the child would
otherwise be racing the parent for that one.

Reporting the reason as well needs a schema field, which is a
conversation with the telemetry service team rather than something to
sneak in here.

Error handling now happens in one place per process:

- The sink's dispatch() throws instead of returning a boolean that meant
  "should the caller keep the batch?", and flush() logs once. The batch
  is always cleared: delivery is one-shot, the process that would retry
  has usually exited, and retaining it just regrew the batch and
  re-logged the same failure every 30 seconds. That also settles the
  no-sender-path case, which never starts working mid-process.
- sendTelemetry() returns the status code and lets real errors propagate
  rather than converting everything into a result object. Judging a
  non-2xx and catching failures both happen in the entry point, which is
  also where the breadcrumb is written.

CDK_TELEMETRY_SENDER_DEBUG=1 now passes the child's stderr through
instead of spawning with stdio:'ignore', which made the only field-debug
tool we have unusable.

Also fixes a query string being dropped from the endpoint URL: the POST
path was url.pathname, so ?foo=bar was silently discarded.
…t it

Nearly every telemetry test asserted on the 'Telemetry dispatched' trace,
which the parent emits when it hands the batch over. That proves the
hand-off and nothing else -- the POST happens in a child that outlives the
CLI, so its output cannot appear in ours. Point TELEMETRY_ENDPOINT at a
local HTTPS server instead and wait for the request to turn up there,
which covers the whole chain: temp-file hand-off, resolving and spawning
the sender, forwarding the CA path, and the request itself.

The endpoint is mockttp, reusing what the proxy tests already use. That
matters for a specific reason: it mints a leaf certificate for the host
we ask for, signed by the CA we give it, so --ca-bundle-path genuinely has
to work for delivery to succeed. A bare self-signed certificate would fail
hostname verification instead, which is why the existing proxy test could
only check the CLI -> proxy hop.

Added:

- a direct-path test that waits for the batch and checks the payload
  carries no certificate bytes;
- a real negative test for both CDK_DISABLE_CLI_TELEMETRY and the
  persisted cli-telemetry --disable setting: point at a live endpoint and
  assert nothing arrives during a quiet period long enough that a
  successful delivery would have shown up;
- a >64KB CA bundle test, which is the regression that started all of
  this. Built by concatenating certificates until it is bigger than the
  cap that used to drop them, the way a real system bundle is.

The does-not-block test now proves both halves. It used to compare two
wall-clock samples, which would also have passed if telemetry were
silently broken and nothing was sent at all; it now also requires the
black hole to have received a connection. Compares the fastest of two
runs rather than one sample each, and states the invariant that the
threshold has to stay below the sender's network timeout, or the test
cannot fail.

Replaced the assertion that the spawn options are shaped a certain way
(detached/stdio/windowsHide/cwd handed back to us by our own mock) with
one that checks the behaviour those options exist for: a driver process
using the real sink exits while the sender it spawned is still running.

Also corrected the proxy test's description, which still said the child
had only Node built-ins and re-implemented CONNECT itself.
The justification for each decision was written as a paragraph next to the
code, which is the wrong place for it: it belongs in the PR, where it can
be argued about and then forgotten. Cut the multi-paragraph blocks down to
a line or two each and dropped the editorialising. What is left is either
a one-line "why", or the @default JSDoc the repo convention requires on
exported interface properties.

Documented CDK_TELEMETRY_SENDER_DEBUG under Environment, and noted in the
cli-telemetry section that delivery happens in the background so a failure
will not show up in the CLI's output. Also documented
CDK_DISABLE_CLI_TELEMETRY, which turns out never to have been listed
there. CDK_TELEMETRY_SENDER is gone, so there is nothing to document.
Cut the previousSendFailed breadcrumb, close two silent failure paths, and tighten
the boundaries the detached sender depends on.

- Cut the `previousSendFailed` breadcrumb entirely (`last-send.ts` and its test).
  `counters` is a closed schema, so the key was never readable by the endpoint, and
  the wiring was lossy in three independent ways: the 30s flush interval let several
  senders race on one non-atomic file, the outcome was consumed at `begin()` but only
  attached when an event was emitted, and it was consumed even when the only sink was
  the local file sink. A replacement observability design is deferred.

- Delete the orphaned `EndpointTelemetrySink` and its test. It was the sink
  `SubprocessTelemetrySink` replaced; wiring it back as a fallback would have
  reintroduced the blocking network call on the exit path that this work removes.
  Both hand-off failures already trace, so they now report how much was dropped
  rather than only why. `funnel.test.ts` was an `EndpointTelemetrySink` suite in
  disguise (it mocked `https.request`); it now tests the Funnel's own contract
  against real file sinks.

- Pin TLS identity to the destination host unconditionally. `https-proxy-agent` does
  the TLS upgrade itself without handing that host to `tls.connect`, so an
  IP-literal endpoint had nothing to match against and skipped the check. This was
  opt-in via `verifyIdentityAgainst` with exactly one caller passing it.

- Consolidate the copy-pasted deep imports of `ToolkitError` into `lib/toolkit-error.ts`,
  so the path that keeps the toolkit barrel out of the sender bundle is stated once.

- Preserve an explicitly empty proxy across the process boundary. `--proxy ''` means
  "go direct"; unset means "auto-detect from the environment". `Settings.get()` is
  untyped and can surface unset as an empty array, so normalize at the point the
  setting enters typed code without collapsing `''` into `undefined`.

- Integ: let mockttp pick a free telemetry-endpoint port instead of guessing one out
  of a range, which collides under parallel suites with no retry to recover.

- Integ: budget the block-exit overhead relative to the measured baseline, floored and
  capped below the sender's own network budget, so a loaded runner does not flake while
  a real regression is still caught.
Close the spawn-failure hole, prove the cleanup path, and correct a narrative that
described a bug which never shipped.

Blockers:

- Report a refused spawn as a failure. Node does not throw when it refuses a spawn
  (ENOENT, EACCES, EMFILE); it reports on the child's `error` event, which fires after
  the hand-off has already returned. So the realistic failures traced a successful
  dispatch with `pid undefined` and the batch was silently counted as sent, never
  reaching the drop path. libuv does leave `pid` unset synchronously, so check that and
  route into the existing handling. The `error` handler stays for the residual case
  where the spawn is accepted and fails afterwards.

- Test that residual path. The handler is now pulled off the child and invoked, proving
  it removes the payload file -- otherwise every such failure leaks a temp file. Added
  coverage for the synchronous guard, and relabelled the test that mocked EMFILE as a
  synchronous throw, which is not a shape Node produces.

- Split `cdk-telemetry-disabled-posts-nothing` into one integTest per file; it was the
  only file in the directory carrying two.

- Drop the "64KB cap regression" framing. Verified against origin/main: no payload cap
  has ever existed there in any commit, and the telemetry POST is made in-process with
  the CA bundle passed as an `https.Agent`, so payload size is structurally unrelated
  to CA-bundle size. The cap existed only between two commits on this branch and never
  shipped. These tests pin an invariant -- the payload carries a CA path, not cert
  bytes, so batch size is independent of the bundle's -- so they now say that, and
  assert it. Also removed a stale reference to the in-process sink's 500ms budget, which
  this PR deletes.

Nits:

- Trace honesty: nothing connects to an endpoint any more, so `Endpoint Telemetry
  connected` / `NOT connected` become `Telemetry sink registered` / `Telemetry
  disabled`. Dropped the integ assertion on that string; `waitForBatch` below it is the
  real one.
- Removed `closeConnection`, whose single caller always passed true, and the unused
  `diagnostics` parameter on `sendTelemetry`.
- Normalize `caBundlePath` at the same boundary as `proxy`, through one shared helper:
  an empty array is truthy, so it slipped past every guard and reached
  `path.resolve([])`, whose TypeError the resolver swallowed -- silently discarding the
  bundle.
- Exported `DISPATCHED_TRACE` for the unit test rather than repeating the literal, and
  replaced a poke at the sink's private `senderPath` with an injectable resolver.
- Connect to 127.0.0.1 where a test binds to it and does not care about the hostname:
  `localhost` resolves to ::1 first on a dual-stack box under Node 18+, which would
  ECONNREFUSED. Kept the hostname where NO_PROXY and the CONNECT target assert on it.
- Documented why `toolkit-error.ts` cannot just re-use `api-private.ts`, sorted the
  README env-var list, and trimmed the disabled-posts-nothing quiet periods to 5s using
  the existing `sleep` helper.
Both failures are this PR's own new tests, and both come from an assumption about the
environment that holds locally but not on CI.

SOCKS unit tests (build, collect):

`socks5://`, unlike `socks5h://`, resolves the destination on the client side and puts
the resulting address into the SOCKS request. The endpoint was addressed as `localhost`,
so what landed there depended on how that resolved: an IPv6-first runner produced an
ATYP=0x04 address, which the hand-rolled test SOCKS server does not implement -- it ends
the socket, surfacing as `Error: Socket closed`. Address the endpoint by IP in those two
tests, which is not resolved at all and so has the same shape everywhere. Reproduced
locally with `--dns-result-order=ipv6first` (both tests failed identically) and confirmed
fixed under both orders. Preferred over teaching the test server ATYP=0x04, which would
have added an untested code path to test scaffolding. The certificate already covers
`IP:127.0.0.1`, and `localhost` is left alone where it is load-bearing: the NO_PROXY test
and the CONNECT-target assertion.

Telemetry integ tests (integ_telemetry):

The tests handed the throwaway endpoint CA to the whole CLI via `--ca-bundle-path`, which
REPLACES the trust store rather than adding to it. The SDK's own call to a public AWS
endpoint then had no issuer for it, so `STS.GetCallerIdentity` failed, the default
account never resolved, the fixture app's context lookup threw
StackAccountRegionNotSpecified, and `cdk synth` exited 1 -- before any telemetry
assertion ran. Telemetry itself was working; the log showed the batch being dispatched.

Supply the CA through `NODE_EXTRA_CA_CERTS` instead, which adds to the default store, so
public roots keep verifying while the detached sender still trusts the local endpoint.
Verified against the real sender binary: with no CA anywhere delivery fails, with only
`NODE_EXTRA_CA_CERTS` it succeeds, and a public TLS request still verifies with it set
but fails with UNABLE_TO_GET_ISSUER_CERT_LOCALLY when the store is replaced -- the CI
error. The negative control matters: the endpoint's certificate is still verified, so a
successful delivery still means something.

The CA is kept in the two disable tests even though nothing should reach the endpoint:
without a trusted CA, "nothing arrived" would also be true of an enabled run whose
handshake merely failed, and those tests would pass for the wrong reason.

Payload `caBundlePath` forwarding is unchanged and still covered where it can be
asserted in isolation: the `reads the CA bundle from the path it was given` sender test
(a real child, with a negative control) and the proxy integ test, which is left as-is.
@rix0rrr

rix0rrr commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

It would be helpful to re-review if you could go through our comments and either respond to them if you have questions or disagree, or close the conversation if you feel you've addressed the request. Thanks! 🙏

@sanjanaravikumar-az

Copy link
Copy Markdown
Contributor Author

I reworked most of the design, and made some changes:

Sink

  • Added a new SubprocessTelemetrySink instead of mutating the existing endpoint sink. The endpoint sink was left untouched, then deleted once nothing referenced it.

Proxy

  • The sender is now a second bundled entry point (sender-bundle.js) so it can just use the real proxy-agent like cdk-assets and integ-runner already use.
  • Bundle is ~487KB gz. ~1MB of that is the PAC WASM, which is already in index.js. Keeping it: PAC/SOCKS support is the entire reason corporate-proxy users need this.

No env-var handshake

  • removed CDK_CLI_BIN_PATH and cli-bin-path.ts, and bin/cdk is reverted to its original 3 lines. The sender is resolved by path and spawned as sender-bundle.js.

Test servers

  • One shared disposable helper (dispose/using), used by both the unit tests and the integ tests. No inline servers left.

Payload hand-off

  • File hand-off instead of the stdin size cap. The payload goes to a file and carries the CA path, not the cert bytes, so batch size no longer depends on bundle size. There's a regression test with a >128KB CA asserting the payload stays under 4KB.

Error handling

  • One place now: dispatch() throws, flush() logs once.
  • node reports spawn failures asynchronously, so a failed spawn was reading as success. Now child.pid === undefined throws and surfaces as a single Dropped N event(s).
  • Dropped previousSendFailed

Tests assert delivery, not logs

  • mockttp endpoint everywhere. Positive tests assert the batch actually arrives; negative tests assert nothing arrives after a quiet period. The block-exit test asserts both that a connection was made and that the CLI had already exited.

@sanjanaravikumar-az

Copy link
Copy Markdown
Contributor Author

It would be helpful to re-review if you could go through our comments and either respond to them if you have questions or disagree, or close the conversation if you feel you've addressed the request. Thanks! 🙏

yes so sorry for the late replies, redid the design now with your suggestions!

@github-actions

Copy link
Copy Markdown
Contributor

Total lines changed 1584 is greater than 1000. Please consider breaking this PR down.

sanjrkmr and others added 2 commits August 27, 2026 17:48
The two `socks5://` tests asserted only `proxy.connects).toHaveLength(1)`,
i.e. that something reached the proxy. The endpoint is reachable directly
from the test, so a send that silently bypassed the proxy would still have
delivered and still have resolved 200 -- the count was the only thing
standing between a bypass and a green test, and it says nothing about where
the proxy was told to go.

Assert the destination instead, matching what the CONNECT test already does
with `connects[0]`. The SOCKS server learns that address only by parsing it
off the wire, so asserting it is what makes these tests evidence that the
CLI's own proxy resolution routed the send rather than the test setting it up.

Also cover `socks5://` in the fail-closed test, which only exercised
`http://`. The two schemes fail closed in different places: the CONNECT
tunnel never opens, and the SOCKS handshake never starts.

Tests only; no production code touched.

@rix0rrr rix0rrr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost there!

// Check the trace that telemetry was not executed successfully
expect(output).not.toContain('Telemetry Sent Successfully');
// Check the trace that telemetry was never handed to a sender
expect(output).not.toContain('Telemetry dispatched');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And yet here and below I still see assertions on expect(output). Let's get rid of those.

Here is how to write tests (ideally):

One conceptual behavior is asserted per test

Any assertion is either:

  • The behavior we are testing, which we should only be testing once; OR
  • A proxy for the behavior we are testing (for example, sending to the endpoint is hard to test so we test for a log line instead)

In this case, "sending to the endpoint", or "asserting on the data that gets sent" is NOT hard to test, so we don't need to test for a proxy.

Is "this log line appears in the output" the behavior we are testing? If we did want to write a test to say "the log contains X when telemetry is sent", then we would have written a single test to assert exactly that. So there is no reason for this to appear in 10 different tests.

This is either copy/paste detritus, or tests are asserting too much at once. In either case, we should get rid of those asserts.

I know you didn't make this mess, but you did touch it and we always leave the camping grounds cleaner than we found them 😉 .

Comment thread packages/aws-cdk/lib/cli/telemetry/sender-bundle.ts Outdated
Comment thread packages/aws-cdk/lib/cli/telemetry/sender-bundle.ts
Comment thread packages/aws-cdk/lib/toolkit-error.ts Outdated
sanjrkmr and others added 10 commits August 31, 2026 19:42
Assert one behavior per telemetry integ test, use `.finally()` in the sender
entry point, and rename `lib/toolkit-error.ts` to `lib/api-private-error.ts`.

The three integ tests that asserted on a trace line already assert on what
reaches the endpoint (a batch arrives, or nothing arrives after a quiet
period), so the log-line assertions were a proxy for something already
covered directly. Each test keeps its delivery/absence assertion.

`void main().finally(done)` replaces `.then(done, done)`. `done` clears the
hard-kill timeout and exits 0 on both paths; `finally` re-raises a rejection,
but `process.exit(0)` runs synchronously inside it, so nothing is left to
report -- verified against a real endpoint, including under
`--unhandled-rejections=strict`.

`api-private-error.ts` names the file after what it is: the same idea as
`api-private.ts`, deliberately narrower so the sender's bundle does not pull
in the whole toolkit. Header comment trimmed to that one fact.
…d spawn

Telemetry integ tests were proving delivery by matching a trace line the CLI
prints on hand-off ('Telemetry dispatched'). That line is a proxy for behaviour
we can assert directly, and it had spread across six tests.

- cdk-cli-telemetry-disable-sends-no-data: had ONLY trace assertions, so there
  was nothing to fall back on. Converted to the shared disposable endpoint
  helper: point TELEMETRY_ENDPOINT at a real local server, run
  `cli-telemetry --disable`, wait the quiet period, assert nothing was POSTed.
  This covers the `canCollectTelemetry` special case for that command (the
  persisted setting is written by that very run, so it cannot be what
  suppresses it) -- a different route than
  cdk-telemetry-disable-command-posts-nothing, which proves a SUBSEQUENT
  command honours the setting this one writes.
- deploy / hotswap / synth / guessagent / synth-with-errors: each already
  asserted the telemetry file's contents, so the trace assertion was
  redundant. Dropped it, and the now-unused `const output` binding with it.

Left alone deliberately: cdk-invalid-command-telemetry keeps
`toContain('Session instantiated with an invalid command')` -- that is the
only positive signal the invalid-command path was reached, and the
file-absence assertion alone would also hold if the CLI died early. Same for
cdk-cli-telemetry-reports-status, where the printed message IS the command's
contract rather than a debug trace.

DISPATCHED_TRACE's doc comment no longer claims integ tests match the literal;
only the unit tests use it, and they import the constant.

Separately, main banned direct node:child_process imports under
packages/aws-cdk/lib (5766544), which the `collect` job already trips because
it builds this PR merged with main. Added a justified disable at the import:
the sender is detached and unref'd so it can outlive the CLI, whereas
run/runSync from the sanctioned subprocess tool monitor the child to
completion. Same precedent main uses for its own subprocess wrapper.
… — assert telemetry via endpoint only

The 'This is an error' output-text assertion in cdk-synth-telemetry-with-errors.integtest.ts was a copy/paste log-line proxy. The test's single conceptual behavior (telemetry records INVOKE/SYNTH FAILED with error name synth:AnnotationErrors) is already fully asserted directly via the JSON telemetry file below it, so the proxy assert is removed with no new assertion needed.
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

This branch had an error being deployed

1 failed (outdated) and 2 active deployments
run-tests 3992d035 Deployed Sep 23, 2026 by sanjanaravikumar-az via integ_cli (cli-integ-tests, 24.19, 3) #6991
no-approval 3992d035 Deployed Sep 23, 2026 by sanjanaravikumar-az via prepare #6991
automation b710b277 Deployed Jul 29, 2026 by sanjanaravikumar-az via Set AutoQueue on PR #1779 #3182
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants