investigating-error-issue
Investigates a single PostHog error tracking issue end-to-end. Use when the user provides an issue ID or pastes an issue URL (`/error_tracking/<id>`) and wants to understand the error — who it affects, what triggers it, when it started, whether it correlates with a release, browser, OS, or feature flag, and what the next step should be. Pulls aggregated metrics, sample exception events, segment breakdowns, linked replays, and synthesizes a hypothesis-grade summary in one pass.
What this skill does
# Investigating an error tracking issue
When a user asks "what's going on with this error?" or pastes an issue URL, gather
the context they would otherwise have to assemble manually: who is hitting it, what
changed, where it happens, and whether a replay shows the cause.
## Available tools
| Tool | Purpose |
| ------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `posthog:query-error-tracking-issue` | Compact issue details (status, assignee, top frame, release, aggregates) |
| `posthog:query-error-tracking-issue-events` | Sampled `$exception` events with stack, URL, browser, `$session_id` |
| `posthog:execute-sql` | Breakdowns, release / flag correlations, surrounding events + console logs around the error |
| `posthog:query-logs` | OTEL log entries around the error timestamp for server-side issues |
| `posthog:query-session-recordings-list` | Linked replays (delegate ranking to `finding-replay-for-issue`) |
| `posthog:read-data-schema` | Confirm property keys before filtering on them |
## Workflow
### Step 1 — Establish the issue baseline
Fetch the issue record with its compact aggregates and a sparkline:
```json
posthog:query-error-tracking-issue
{
"issueId": "<issue_id>",
"dateRange": { "date_from": "-30d" },
"includeSparkline": true,
"volumeResolution": 12
}
```
Capture: `name`, `description`, `status`, `first_seen`, `last_seen`, `assignee`,
total `occurrences` / `users` / `sessions`, top in-app frame, latest release
metadata, and the volume buckets.
The sparkline tells you the shape — flat, spike, ramp, or recurring — and that
shape drives the rest of the investigation. If the user only asked a status
question, skip `includeSparkline` to save tokens.
### Step 2 — Pull a sample exception event
A captured event has the stack frames, URL, browser, and properties needed to
reason about cause. Pull a recent sample first, then an early one to compare.
```json
posthog:query-error-tracking-issue-events
{
"issueId": "<issue_id>",
"limit": 1,
"verbosity": "stack"
}
```
Use `verbosity: "raw"` only if the truncated stack hides the answer. The tool
defaults to `onlyAppFrames: true`, which strips vendor frames; flip to `false`
when the bug appears to live in a third-party library — or when the response
comes back with `stacktrace.type: "resolved"` but no frames at all (common for
minified bundles where every frame looks vendor-y to the resolver, e.g. React
production builds).
For the earliest sample, narrow `dateRange` to a tight window around the
issue's `first_seen` (e.g. set `date_from` slightly before and `date_to`
slightly after) and pass `orderDirection: "ASC"` so you get the earliest
event in the window rather than the latest — the tool defaults to `DESC`,
which would return a recent event and silently duplicate the first call.
If recent and earliest events look materially different — different stack
root, different URL pattern — the issue may be a grouping mistake. Flag for
`grouping-noisy-errors` instead of continuing as if it were one bug.
### Step 3 — Run breakdowns to isolate the cause
Breakdowns aren't a typed tool — drop into `execute-sql`. Run only the
breakdowns the issue's shape suggests; each one costs a query and clutters the
synthesis.
| Sparkline shape | First breakdown to try |
| ----------------- | ------------------------------------------------------------------------ |
| Spike from zero | By app version / release — almost always a deploy regression (see below) |
| Steady-state high | By browser / OS — rendering or platform-specific bug |
| Ramp | By geography or feature flag — gradual rollout exposure |
| Bursts then quiet | By time of day or `$current_url` — scheduled job or specific page |
#### Picking the right version property
PostHog emits three version-shaped fields. They mean different things and only
one of them answers "what version of the user's app introduced this?":
| Property | What it is | Auto-captured by | Use for |
| --------------------- | --------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| `$exception_releases` | Cymbal-managed release map, keyed by release ID | Only when SDK publishes release metadata (e.g. sourcemap upload tied to a release) | Most precise release attribution **when present** |
| `$app_version` | The user's deployed app version | iOS (`CFBundleShortVersionString`), React Native (Expo / react-native-device-info) | "What deploy of my app introduced this?" — the question users care about |
| `$lib_version` | The PostHog SDK library version (e.g. posthog-js 1.298.0) | Every SDK on every event | The narrow "did upgrading the PostHog SDK introduce this?" question |
`$lib_version` is on virtually every event, which makes it tempting — but it's
the PostHog library version, not the user's app version. A constant
`$lib_version` paired with a spike means the user shipped a regression in
their own code with the SDK unchanged, which is the common case. Reach for
`$lib_version` only when nothing else is populated and you're explicitly
asking "did upgrading PostHog cause this?".
Web / server / Node / Java / Python projects do **not** auto-capture
`$app_version` — the customer has to set it (via `register`, a context
provider, or `before_send`). If the breakdown comes back with one
`$app_version` row of all-NULL, say so explicitly in the synthesis and
suggest the customer wire it up; falling back to `$exception_releases` or to
a per-day timeline by `first_seen` keeps the investigation moving.
Example (`$app_version` — populated automatically on mobile, manually on
web / server):
```sql
posthog:execute-sql
SELECT
properties.$app_version AS app_version,
count() AS occurrences,
uniq(person_id) AS users,
min(timestamp) AS first_seen,
max(timestamp) AS last_seen
FROM events
WHERE event = '$exception'
AND (issue_id = '<issue_id>' OR properties.$exception_issue_id = '<issue_id>')
AND timestamp > now() - INTERVAL 30 DAY
GROUP BY app_version
ORDER BY occurrences DESC
LIMIT 20
```
The `(issue_id = ... OR properties.$exception_issue_id = ...)` pattern
mirrors the canonical `build_issue_where` clause from
`products/error_tracking/backend/api/query_utils.py`. `issue_id` is the
resolved virtual field on `events` (it follows fingerprint overrides so
merged/split issues route correctly); `properties.$exception_issue_id` is
the raw event property captured at ingestion. Filtering on only the property
silently undercounts events for issues that have been merged or split.
If `first_seen` for one `app_version` is much later than the issue's overall
`first_seen`, that release introduced or worsened the bug — strong root-cause
signal. If every row is `NULL`, the SDK isn't reporting an app version on
this project (common on web / server) — switch to `$exception_releases` if
the customer ships releases, or fall back to a `toDate(timestamp)` timeline.
When `$exception_releases` is populated, it's a JSON dict keyed by release
ID. There is no top-level `$rRelated in Data & Analytics
clawarr-suite
IncludedComprehensive management for self-hosted media stacks (Sonarr, Radarr, Lidarr, Readarr, Prowlarr, Bazarr, Overseerr, Plex, Tautulli, SABnzbd, Recyclarr, Unpackerr, Notifiarr, Maintainerr, Kometa, FlareSolverr). Deep library exploration, analytics, dashboard generation, content management, request handling, subtitle management, indexer control, download monitoring, quality profile sync, library cleanup automation, notification routing, collection/overlay management, and media tracker integration (Trakt, Letterboxd, Simkl).
querying-soql
IncludedSOQL query generation, optimization, and analysis with 100-point scoring. Use this skill when the user needs SOQL/SOSL authoring or optimization: natural-language-to-query generation, relationship queries, aggregates, query-plan analysis, and performance or safety improvements for Salesforce queries. TRIGGER when: user writes, optimizes, or debugs SOQL/SOSL queries, touches .soql files, or asks about relationship queries, aggregates, or query performance. DO NOT TRIGGER when: bulk data operations (use handling-sf-data), Apex DML logic (use generating-apex), or report/dashboard queries.
app-store-optimization
IncludedApp Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklists, and tracking ranking changes.
habit-flow
IncludedAI-powered atomic habit tracker with natural language logging, streak tracking, smart reminders, and coaching. Use for creating habits, logging completions naturally ("I meditated today"), viewing progress, and getting personalized coaching.
app-store-optimization
IncludedApp Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklists, and tracking ranking changes.
visualizing-data
IncludedBuilds dashboards, reports, and data-driven interfaces requiring charts, graphs, or visual analytics. Provides systematic framework for selecting appropriate visualizations based on data characteristics and analytical purpose. Includes 24+ visualization types organized by purpose (trends, comparisons, distributions, relationships, flows, hierarchies, geospatial), accessibility patterns (WCAG 2.1 AA compliance), colorblind-safe palettes, and performance optimization strategies. Use when creating visualizations, choosing chart types, displaying data graphically, or designing data interfaces.