Skip to content

fix(query): stop capturing expected user query errors into error tracking#67275

Draft
posthog[bot] wants to merge 1 commit into
masterfrom
posthog-code/suppress-expected-query-error-capture
Draft

fix(query): stop capturing expected user query errors into error tracking#67275
posthog[bot] wants to merge 1 commit into
masterfrom
posthog-code/suppress-expected-query-error-capture

Conversation

@posthog

@posthog posthog Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Claude-written:

Problem

Query error tracking was getting polluted by expected user-input errors. When a HogQL query runs against a direct Postgres / data-warehouse source and exceeds the Postgres statement_timeout, Postgres raises QueryCanceled; the adapter re-raises it as an ExposedHogQLError, which bubbles up through QueryRunner.run. That method wraps execution in a posthoganalytics.new_context() block, which auto-captures any exception raised inside it into error tracking.

The catch: the runner already classifies ExposedHogQLError as a USER_ERROR and counts it as an SLO success. So we were capturing something we've explicitly decided is normal user input, not a platform failure. The person running the slow query gets a clean error message back, but we still opened an error-tracking issue for it. Low volume today, but it fires every time a warehouse query is too slow, so it's ongoing triage noise and a source of false alarms.

Changes

Disable auto-capture on the new_context() boundary in QueryRunner.run and capture manually instead, gated on the SLO outcome the runner already computes:

  • SLO-success outcomes (user errors, cancellations, rate limits) are expected input and are no longer captured into error tracking.
  • SLO-failure outcomes (query performance errors, unclassified exceptions) are captured explicitly, from inside the context, so the same context tags (cache_key, query_type, insight_id, etc.) are still attached as before.

This is the general form of the fix the report suggested: the runner already knows which errors are expected, so suppress those at the capture boundary while letting genuine platform errors surface unchanged.

How did you test this code?

I could not run the suite in this sandbox (test dependencies aren't installed here), so I did not execute the tests. I verified both changed files byte-compile and traced the control flow to confirm the outer boundary is the only exception-capture point on this path (_execute_and_cache_blocking's inner except only increments metrics and re-raises).

I extended the existing parameterized test test_run_classifies_slo_error_at_except_boundary rather than adding a new one — it already exercises exactly the SUCCESS/FAILURE outcomes I care about. The new assertion catches the regression that expected user-input errors would again be captured into error tracking if auto-capture were re-enabled or the manual guard removed: capture_exception must not be called for SLO-success outcomes and must be called once for failures.

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

Docs update

No docs changes needed.

🤖 Agent context

Autonomy: Fully autonomous

Authored by Claude (via PostHog Code) from an inbox report about a new error-tracking issue that turned out to be an expected direct-Postgres warehouse query timeout. Invoked the /writing-tests skill before touching tests, which steered me to extend the existing SLO-boundary parameterized test rather than write a redundant new one.

Considered two options from the report: narrowly special-casing the wrapped QueryCanceled statement-timeout in postgres_adapter.py, versus suppressing at the new_context capture boundary. Chose the boundary fix because the runner already classifies these as SLO-success, so keying capture off that existing classification is more principled and also covers other expected user-input errors (cancellations, rate limits) that were being captured for the same reason. posthoganalytics.new_context has no per-exception filter, so the mechanism is: disable its auto-capture and call posthoganalytics.capture_exception manually for failures only.


Created with PostHog Code from an inbox report.

…king

The query runner's `posthoganalytics.new_context()` boundary auto-captured
every exception raised during a query, including ones the runner already
classifies as SLO-success (user errors, cancellations, rate limits). A direct
Postgres / data-warehouse query exceeding statement_timeout surfaces as an
ExposedHogQLError, so it was creating error-tracking issues even though the user
gets a clean error message and we treat it as expected input.

Disable auto-capture on the context and capture manually only for genuine
platform failures (SLO-failure outcomes), preserving the same context tags.

Extends the existing SLO-boundary test to assert capture_exception is invoked
for failures and suppressed for expected user-input errors.

Generated-By: PostHog Code
Task-Id: f56d2296-ef23-4f54-935f-794a6bce8138
@scheduled-actions-posthog

Copy link
Copy Markdown
Contributor

This PR hasn't seen activity in a week! Should it be merged, closed, or further worked on? If you want to keep it open, please remove the stale label – otherwise this will be closed in another week. If you want to permanently keep it open, use the waiting label.

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.

0 participants