Skip to content

fix(frontend): reduce noisy PostHog client errors#1918

Merged
riderx merged 1 commit into
mainfrom
codex/fix-posthog-error-noise
Apr 17, 2026
Merged

fix(frontend): reduce noisy PostHog client errors#1918
riderx merged 1 commit into
mainfrom
codex/fix-posthog-error-noise

Conversation

@riderx
Copy link
Copy Markdown
Member

@riderx riderx commented Apr 17, 2026

Summary (AI generated)

  • suppress known crawler-only Object Not Found Matching Id:* client errors before they reach PostHog
  • keep the PostHog before_send suppression aligned with the same crawler-noise matcher
  • guard chart drawing plugins when Chart.js no longer has a live canvas context, which stops repeated null.save crashes
  • add unit coverage for the new error filtering and chart plugin guard paths

Motivation (AI generated)

PostHog error tracking is currently dominated by two frontend-only problems: crawler-generated noise from email link scanning, and chart plugin redraws that run after the canvas context is gone. Those issues hide real regressions and waste time during triage.

Business Impact (AI generated)

This reduces false-positive production noise in PostHog so real customer-facing errors stay visible, and it removes a real chart crash affecting mobile users on stats and bundles views. Cleaner monitoring improves support response and lowers the risk of missing genuine regressions.

Test Plan (AI generated)

  • bunx vitest run tests/stale-asset-errors.unit.test.ts tests/chart-plugins.unit.test.ts
  • bun run typecheck
  • GitHub Actions CI passes

Generated with AI

Summary by CodeRabbit

  • Bug Fixes

    • Improved error handling for crawler-related and stale-asset errors to reduce noise in error reporting
    • Enhanced chart rendering stability when the rendering context is unavailable
    • Optimized tooltip state management during user interactions
  • Tests

    • Added tests for chart plugin robustness and error suppression logic

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 17, 2026

📝 Walkthrough

Walkthrough

The pull request adds detection and suppression for "known crawler noise" errors (specifically "Object Not Found Matching Id" patterns) in window error event handlers and PostHog exception suppression logic. Additionally, chart plugin rendering logic and tooltip management are enhanced with canvas context validation helpers to prevent errors when the rendering context is unavailable.

Changes

Cohort / File(s) Summary
Crawler Noise Error Handling
src/main.ts, src/services/staleAssetErrors.ts
Added new predicate isKnownCrawlerNoiseErrorMessage to detect crawler-specific error patterns. Updated window error and unhandledrejection event handlers to separately detect and suppress crawler noise via preventDefault() and stopImmediatePropagation() without invoking chunk reload logic. Extended shouldSuppressPostHogExceptionEvent to also suppress crawler noise errors.
Chart Plugin Context Validation
src/services/chartAnnotations.ts, src/services/chartTooltip.ts
Added getCanvasContext() validation helpers in both files to guard against missing or invalid canvas rendering contexts. Updated plugin drawing logic to early-return when context is unavailable. In tooltip service, introduced canSafelyUpdateChart and clearTooltipSelection helpers to safely manage chart state updates based on context availability.
Test Coverage
tests/chart-plugins.unit.test.ts, tests/stale-asset-errors.unit.test.ts
Added Vitest suite validating chart plugin early-exit behavior when canvas context is unavailable. Extended stale-asset error tests with coverage for isKnownCrawlerNoiseErrorMessage predicate and updated shouldSuppressPostHogExceptionEvent suppression behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 Crawlers hop and stumble about,
Leaving noise that we filter out!
Charts now check their canvas twice,
Guards and helpers keep things nice. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main objective: reducing noisy PostHog client errors through filtering and guards.
Description check ✅ Passed The description includes Summary, Motivation, Business Impact, and Test Plan sections, but is missing Screenshots (noted as skippable) and incomplete Checklist.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-posthog-error-noise

Comment @coderabbitai help to get the list of available commands and usage tips.

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented Apr 17, 2026

Merging this PR will not alter performance

✅ 28 untouched benchmarks


Comparing codex/fix-posthog-error-noise (1f679b4) with main (0ee3b8c)

Open in CodSpeed

@riderx riderx marked this pull request as ready for review April 17, 2026 12:06
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (5)
tests/stale-asset-errors.unit.test.ts (2)

3-3: Use ~/ alias for the service import.

Replace ../src/services/staleAssetErrors with the project alias form.

🔧 Suggested change
-import { getErrorMessage, isKnownCrawlerNoiseErrorMessage, isStaleAssetErrorMessage, shouldSuppressPostHogExceptionEvent } from '../src/services/staleAssetErrors'
+import { getErrorMessage, isKnownCrawlerNoiseErrorMessage, isStaleAssetErrorMessage, shouldSuppressPostHogExceptionEvent } from '~/services/staleAssetErrors'

As per coding guidelines "**/*.ts: Use path alias ~/ to map to src/ for cleaner imports".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/stale-asset-errors.unit.test.ts` at line 3, Update the import in the
test to use the project path alias instead of a relative path: replace the
import source '../src/services/staleAssetErrors' with the alias form
'~/services/staleAssetErrors' so the imported symbols get resolved via the src/
alias; keep the imported names getErrorMessage, isKnownCrawlerNoiseErrorMessage,
isStaleAssetErrorMessage, and shouldSuppressPostHogExceptionEvent unchanged.

22-27: Convert this new matcher test to it.concurrent().

This case is independent and can run in parallel safely.

⚡ Suggested change
-  it('matches the known crawler-only Object Not Found noise seen in PostHog', () => {
+  it.concurrent('matches the known crawler-only Object Not Found noise seen in PostHog', () => {

As per coding guidelines "tests/**/*.{ts,js}: Use it.concurrent() instead of it() when possible to run tests in parallel within the same file, maximizing parallelism for faster CI/CD".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/stale-asset-errors.unit.test.ts` around lines 22 - 27, The test using
it(...) is safe to run in parallel; change the test declaration to
it.concurrent(...) for the case that asserts isKnownCrawlerNoiseErrorMessage
outputs (replace the current it('matches the known crawler-only Object Not Found
noise seen in PostHog', ...) with it.concurrent(...)). Ensure the test function
name and assertions (isKnownCrawlerNoiseErrorMessage calls) remain unchanged so
only the test runner call is updated.
tests/chart-plugins.unit.test.ts (2)

3-4: Switch test imports to the ~/ alias.

Use the frontend alias instead of relative ../src/... paths for TypeScript consistency.

🔧 Suggested change
-import { inlineAnnotationPlugin } from '../src/services/chartAnnotations'
-import { todayLinePlugin, verticalLinePlugin } from '../src/services/chartTooltip'
+import { inlineAnnotationPlugin } from '~/services/chartAnnotations'
+import { todayLinePlugin, verticalLinePlugin } from '~/services/chartTooltip'

As per coding guidelines "**/*.ts: Use path alias ~/ to map to src/ for cleaner imports".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/chart-plugins.unit.test.ts` around lines 3 - 4, Replace the relative
imports in tests/chart-plugins.unit.test.ts with the project path alias by
changing the import sources for inlineAnnotationPlugin, todayLinePlugin, and
verticalLinePlugin to use the `~/` alias (e.g., import { inlineAnnotationPlugin
} from '~/services/chartAnnotations' and import { todayLinePlugin,
verticalLinePlugin } from '~/services/chartTooltip') so the tests use the
TypeScript frontend alias mapping to src/.

7-82: Run these independent tests concurrently.

These three plugin guard tests are isolated and can use it.concurrent() to improve CI throughput.

⚡ Suggested change
-  it('skips drawing the vertical hover line when the chart context is gone', () => {
+  it.concurrent('skips drawing the vertical hover line when the chart context is gone', () => {
@@
-  it('skips drawing the today line when the chart context is gone', () => {
+  it.concurrent('skips drawing the today line when the chart context is gone', () => {
@@
-  it('skips inline annotations when the chart context is gone', () => {
+  it.concurrent('skips inline annotations when the chart context is gone', () => {

As per coding guidelines "tests/**/*.{ts,js}: Use it.concurrent() instead of it() when possible to run tests in parallel within the same file, maximizing parallelism for faster CI/CD".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/chart-plugins.unit.test.ts` around lines 7 - 82, Replace the three
synchronous tests that call verticalLinePlugin.afterDatasetsDraw,
todayLinePlugin.afterDatasetsDraw, and inlineAnnotationPlugin.afterDatasetsDraw
with concurrent tests by changing it(...) to it.concurrent(...); ensure the test
bodies and assertions remain unchanged so each test still calls the same plugin
method with the same mock chart context and uses expect(...).not.toThrow().
src/services/chartTooltip.ts (1)

24-29: Extract getCanvasContext into a shared helper to avoid drift.

The same helper now exists in both src/services/chartTooltip.ts and src/services/chartAnnotations.ts. Centralizing it keeps guard behavior consistent.

♻️ Proposed refactor
- function getCanvasContext(ctx: unknown): CanvasRenderingContext2D | null {
-   if (ctx && typeof (ctx as CanvasRenderingContext2D).save === 'function')
-     return ctx as CanvasRenderingContext2D
-
-   return null
- }
+ import { getCanvasContext } from '~/services/chartCanvas'
// src/services/chartCanvas.ts
export function getCanvasContext(ctx: unknown): CanvasRenderingContext2D | null {
  if (ctx && typeof (ctx as CanvasRenderingContext2D).save === 'function')
    return ctx as CanvasRenderingContext2D

  return null
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/services/chartTooltip.ts` around lines 24 - 29, Extract the duplicated
getCanvasContext function into a single shared helper module by creating and
exporting function getCanvasContext(ctx: unknown): CanvasRenderingContext2D |
null with the same guard (checking ctx && typeof (ctx as
CanvasRenderingContext2D).save === 'function'), then remove the duplicate
implementations from both modules that currently define getCanvasContext and
update those modules to import and use the shared getCanvasContext export; keep
the signature and behavior identical so callers in chartTooltip and
chartAnnotations continue to work without further changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/services/chartTooltip.ts`:
- Around line 24-29: Extract the duplicated getCanvasContext function into a
single shared helper module by creating and exporting function
getCanvasContext(ctx: unknown): CanvasRenderingContext2D | null with the same
guard (checking ctx && typeof (ctx as CanvasRenderingContext2D).save ===
'function'), then remove the duplicate implementations from both modules that
currently define getCanvasContext and update those modules to import and use the
shared getCanvasContext export; keep the signature and behavior identical so
callers in chartTooltip and chartAnnotations continue to work without further
changes.

In `@tests/chart-plugins.unit.test.ts`:
- Around line 3-4: Replace the relative imports in
tests/chart-plugins.unit.test.ts with the project path alias by changing the
import sources for inlineAnnotationPlugin, todayLinePlugin, and
verticalLinePlugin to use the `~/` alias (e.g., import { inlineAnnotationPlugin
} from '~/services/chartAnnotations' and import { todayLinePlugin,
verticalLinePlugin } from '~/services/chartTooltip') so the tests use the
TypeScript frontend alias mapping to src/.
- Around line 7-82: Replace the three synchronous tests that call
verticalLinePlugin.afterDatasetsDraw, todayLinePlugin.afterDatasetsDraw, and
inlineAnnotationPlugin.afterDatasetsDraw with concurrent tests by changing
it(...) to it.concurrent(...); ensure the test bodies and assertions remain
unchanged so each test still calls the same plugin method with the same mock
chart context and uses expect(...).not.toThrow().

In `@tests/stale-asset-errors.unit.test.ts`:
- Line 3: Update the import in the test to use the project path alias instead of
a relative path: replace the import source '../src/services/staleAssetErrors'
with the alias form '~/services/staleAssetErrors' so the imported symbols get
resolved via the src/ alias; keep the imported names getErrorMessage,
isKnownCrawlerNoiseErrorMessage, isStaleAssetErrorMessage, and
shouldSuppressPostHogExceptionEvent unchanged.
- Around line 22-27: The test using it(...) is safe to run in parallel; change
the test declaration to it.concurrent(...) for the case that asserts
isKnownCrawlerNoiseErrorMessage outputs (replace the current it('matches the
known crawler-only Object Not Found noise seen in PostHog', ...) with
it.concurrent(...)). Ensure the test function name and assertions
(isKnownCrawlerNoiseErrorMessage calls) remain unchanged so only the test runner
call is updated.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a99aa33d-7264-4c7e-b0bc-0585d7e552a1

📥 Commits

Reviewing files that changed from the base of the PR and between 0ee3b8c and 1f679b4.

📒 Files selected for processing (6)
  • src/main.ts
  • src/services/chartAnnotations.ts
  • src/services/chartTooltip.ts
  • src/services/staleAssetErrors.ts
  • tests/chart-plugins.unit.test.ts
  • tests/stale-asset-errors.unit.test.ts

@riderx riderx merged commit c647521 into main Apr 17, 2026
15 checks passed
@riderx riderx deleted the codex/fix-posthog-error-noise branch April 17, 2026 12:19
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.

2 participants