fix(cli): stop PostHog SDK printing stack traces on failed telemetry sends - #817
Conversation
…sends
When the telemetry endpoint is unreachable or returns an error status,
@posthog/core's logFlushError writes the full error — nested stack traces
included — straight to console.error, from both the capture-triggered
background flush and the shutdown flush (two blocks per command). It logs
internally before swallowing the rejection, so the CLI's own .catch(() => {})
wrappers never see it.
Supply the client a fetch wrapper (silentFetch) that absorbs network errors
and HTTP error statuses into a stub 200, so the SDK never observes a failure
and never logs. Discarded error responses are drained so undici releases the
connection, and the SDK's AbortSignal is passed through so the bounded-flush
guarantee holds. Fire-and-forget semantics are unchanged under this client's
flushAt: 1 / fetchRetryCount: 0 config — a failed event was already dropped.
The traces went to stderr, so stash manifest --json stdout was never
corrupted; agent harnesses reporting merged streams read it as stdout.
Closes #740
🦋 Changeset detectedLatest commit: 9085be3 The changes in this PR will be included in the next version bump. This PR includes changesets to release 11 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
📝 WalkthroughWalkthroughThe CLI adds a ChangesTelemetry failure handling
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Code review notesA multi-angle automated code review of this diff was run by Claude (Fable 5) before commit. Ten findings; the three flagged as worth fixing pre-commit were all addressed in this PR:
Two documentation findings were also folded in: the "semantics are unchanged" overclaim in the doc comment was replaced with the two real trade-offs (faking success defeats the SDK's queue retention and 413 batch-splitting — safe only under Remaining findings were noted but deliberately not applied here, as lower-value or follow-up material:
The review also verified the approach's premises against the SDK source: |
freshtonic
left a comment
There was a problem hiding this comment.
Straightforward & well-tested
Closes #740.
Problem
With telemetry enabled (published build, past first run) and the endpoint unreachable or returning an error, every tracked command printed two full stack-trace blocks:
Root cause:
@posthog/core'slogFlushError()hardcodesconsole.error(..., err)and fires from both the capture-triggered background flush (flushAt: 1) and the shutdown flush. The SDK logs internally before swallowing the rejection, so the CLI's.catch(() => {})wrappers never see an error — there is no logger option to silence it.Why the original repro failed: local builds are dormant (placeholder key, nothing ever sent), and the traces go to stderr — the report said stdout because agent harnesses capture merged streams.
stash manifest --jsonstdout was never corrupted, so the AGENTS.md skill-drift check was never at risk; the noise is still a bug (telemetry must never surface).Fix
silentFetch— a fetch wrapper passed to the PostHog constructor that absorbs network errors and HTTP error statuses into a stub 200, so the SDK never observes a failure and never logs:res.body?.cancel()) so undici releases the connection instead of holding the socket past the bounded-flush window.AbortSignal(requestTimeout) is forwarded verbatim, preserving the bounded-flush guarantee.flushAt: 1/fetchRetryCount: 0config — a failed event was already dropped. The doc comment records the two trade-offs (batching would need revisiting; the client must stay capture-only).Tests
fetch: silentFetchin the constructor options so a future refactor or posthog-node upgrade dropping the wiring fails the suite.Changeset:
stashpatch.Summary by CodeRabbit