PostHog / PostHog/posthog

[customer analytics] A single unresolvable column fails the entire accounts list

Open
#68,903 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature/customer-analytics
Dominant language
Python
Stars
39.9k
Forks
3.4k
Avg merge
6h 51m
Merged PRs (30d)
232

Description

Summary

The accounts list builds one HogQL query from all selected columns. If any column references a field that no longer resolves — a removed/renamed data-warehouse join column, stale freeform SQL, or a stale saved view / column config — the whole query throws (Field not found: …, Unable to resolve field: id) and the user sees zero accounts, not just a missing column. There is no per-column isolation in the runner and no reconciliation of stale saved columns against the live schema. The fix is to drop-and-warn unresolvable columns (on the client when applying a saved view, and/or by isolating failing columns in the runner) so the table degrades instead of failing entirely.

Part of #68887.

Details for coding agents

Root cause

  • AccountsQueryRunner._resolve_column only parse_exprs each select string (a syntax check); a reference to a non-existent field passes. The real failure happens later in paginator.execute_hogql_query(...) during HogQL resolution, which raises QueryError (Field not found / Unable to resolve field). Nothing wraps it per-column, so the entire AccountsQuery fails.
  • No validation exists at save time: serializeAccountsView copies columns verbatim; ColumnConfigurationViewSet.create validates only "non-empty list of strings". On load, loadViewsSuccess → applyView → setSelectColumns applies stale column strings without pruning.
  • Field origins: account_health_scores / users_count are almost certainly former DW-join or freeform-SQL aliases whose source table/join was removed — buildAccountColumnGroups silently drops the group, but the saved ColumnConfiguration.columns (and shared #view= hash / currentViewId) still carry the stale expression. properties and bare id fail because they aren't exposed as top-level select aliases on the system.accounts virtual table.

Proposed fix (either or both)

  1. Frontend reconcile (better UX): add a reconcileColumnsAgainstSchema selector in accountsColumnConfigLogic (mirror reconcileTilesAgainstSchema in the tiles logic) that filters selectColumns to those present in accountsColumnGroups; run it after loadViewsSuccess/applyView so stale columns are dropped before the query fires.
  2. Backend isolation (defense in depth): wrap execute_hogql_query in AccountsQueryRunner._calculate in a try/except for (BaseHogQLError, ExposedCHQueryError, InternalCHQueryError); on failure isolate offending columns (like the existing _isolate_failing_metrics pattern) and return a partial result with a warnings field instead of a total failure.

References

  • products/customer_analytics/backend/hogql_queries/accounts_query_runner.py:52-65 (_resolve_column, syntax-only), :224-231 (un-guarded execute_hogql_query), :291-299 (_isolate_failing_metrics reference pattern)
  • products/customer_analytics/frontend/components/Accounts/accountsColumnConfigLogic.ts:177-193 (buildAccountColumnGroups drops stale groups), :215-308 (no reconcile of saved columns)
  • products/customer_analytics/frontend/components/Accounts/accountsViewsLogic.ts:272-297 (loadViewsSuccess applies stale columns)
  • posthog/api/column_configuration.py:103-139 (save-time validation: strings only)
  • posthog/hogql/resolver.py:2030,2036, posthog/hogql/ast.py:242,315,746 — where the Field not found / Unable to resolve field errors originate

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with products/customer_analytics/frontend/components/Accounts/accountsColumnConfigLogic.ts and accountsViewsLogic.ts, comparing their saved-column flow with reconcileTilesAgainstSchema; then inspect accounts_query_runner.py around _resolve_column, _calculate, and _isolate_failing_metrics. Done means stale columns no longer make the accounts list fail completely, with the chosen frontend reconciliation or backend isolation behavior covered by relevant tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, react, typescript
Domain
analytics, backend, frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.