Skip to content

TOF-446: Add per-error troubleshooting pages seeded from Ask-AI and MCP logs - #179

Open
tylergoerzen-mxp with Copilot wants to merge 6 commits into
mainfrom
copilot/tof-446-create-per-error-troubleshooting-pages
Open

TOF-446: Add per-error troubleshooting pages seeded from Ask-AI and MCP logs#179
tylergoerzen-mxp with Copilot wants to merge 6 commits into
mainfrom
copilot/tof-446-create-per-error-troubleshooting-pages

Conversation

Copilot AI commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Adds ten troubleshooting pages under troubleshooting/errors/, plus a hub page.

Relates to: https://linear.app/mixpanel/issue/TOF-446/aeo-qw9-create-per-error-troubleshooting-pages-for-the-top-verified

Why this matters for AEO

Developers paste the exact error string into an assistant. Not a paraphrase, not a category — the literal text their terminal printed. And title-to-query semantic similarity is the largest single citation predictor measured (0.602 cited vs 0.484 non-cited, Ahrefs 1.4M prompts). A page titled with the verbatim error string is close to the best possible retrieval match.

We have direct evidence of this behavior in our own logs rather than inferring it. Real MCP search queries issued by coding agents against our docs:

  • jwt token invalid snowflake 390144 08004 key pair authentication troubleshooting (twice in one month)
  • /import api rate limits requests per second 2gb per minute events per batch
  • $insert_id deduplication window
  • react native production events not showing token init trackautomaticevents

Today those answers sit inside FAQ accordions or do not exist.

Self-containment matters here. These pages restate the relevant limit or prerequisite inline rather than linking away, because an engine extracting a passage will not follow a "see above."

Pages

API status codes400 Bad Request, 401 Unauthorized, 403 Forbidden, 413 Payload Too Large, 429 Too Many Requests

Seeded from the content backlog, drawn from the top three log clusters:

  • Snowflake error 390144: JWT token is invalid — cluster 7, warehouse connectors
  • Duplicate events appearing in reports — cluster 2, $insert_id semantics
  • Backfilled or historical events are not appearing — cluster 2, the /track 5-day window
  • Server-side events with no logged-in user — cluster 1, identity
  • Duplicate or orphaned user profiles — cluster 1, identity

Plus an Error Troubleshooting hub grouping them by what the reader is holding: a status code, a data symptom, an identity problem, or a connector failure.

The five status-code pages were rewritten

The initial drafts described behavior Mixpanel's API does not have. They have been rebuilt against openapi/ingestion.openapi.yaml and reference/import-events.mdx. What changed:

Claim Correction
/import rate limit is 2 GB per hour 2 GB of uncompressed JSON per minute, ~30k events/sec on a rolling one-minute basis. The original would have made anyone throttle a backfill 60× too slowly.
All five example bodies used "code": 0 Real responses return the HTTP status as code plus a status string; /import 400s also carry num_records_imported and per-record insert_id.
429 returns a Retry-After header Mixpanel does not send one. The page now says so and gives the documented backoff: start 2s, double to 60s, 1–5s jitter.
/import request limit is 2 MB 10 MB uncompressed.
Gzip helps avoid 413s The limit is measured against the uncompressed body.
Empty distinct_id causes a 400 The docs instruct you to send an empty string for unattributed events. What is rejected is the placeholder list (anon, null, n/a, …).
Retry a failed batch one event at a time The reference says not to retry 400s at all — they fail consistently and still count against the rate limit.

The 403 page described /import, which never returns a 403 — the spec declares 200, 400, 401, 413, 429. It is now scoped to /track, /engage, and /groups, which do, using the spec's ErrorResponse shape. An invented permission table using the organization role "Member" for a project-level operation, and a nonexistent "user profiles are disabled" project setting, were removed.

Also added: the /track 5-day historical window, a common reason backfilled events never appear.

Scope

Rec #9 targets ~20 pages. This ships 10. The top three log clusters had multiple hits each; below them the evidence thins to single mentions, and filling to 20 means inventing errors — which is how the first draft went wrong. The remaining pages should come from the next log pull rather than from guesswork.

Gaps found, not written up

Three things the logs show users asking that Mixpanel documents nowhere. Filed as TOF-460, TOF-461, TOF-462 rather than answered here:

  • No $insert_id deduplication window exists. The agent query assumes one. The real rule is an exact match on event, time, distinct_id, $insert_id, with no time bound. The duplicate-events page corrects the premise; the reference-side gaps need an owner.
  • No $user_id format guidance exists, and three nearby rules mislead anyone who searches for one.
  • No GA4 identity stitching guide exists, despite a ~20-turn Ask-AI thread on it.

@linear-code

linear-code Bot commented Aug 18, 2026

Copy link
Copy Markdown

TOF-446

Co-authored-by: tylergoerzen-mxp <259741734+tylergoerzen-mxp@users.noreply.github.com>
@mintlify

mintlify Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
mixpanel-docs 🟢 Ready View Preview Aug 18, 2026, 7:08 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

Copilot AI changed the title [WIP] Create per-error troubleshooting pages for top verified error strings TOF-446: Add per-error troubleshooting pages for top Mixpanel API errors Aug 18, 2026
Copilot AI requested a review from tylergoerzen-mxp August 18, 2026 19:02
@greptile-apps

greptile-apps Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 4/5

The retry guidance should be corrected before merging because it can cause duplicate events when callers regenerate part of the deduplication key.

The page assures developers that resending already-ingested events is safe without stating that event, time, distinct_id, and $insert_id must remain identical, even though changing the timestamp or insert ID prevents deduplication.

Files Needing Attention: troubleshooting/errors/400-bad-request.mdx

Important Files Changed

Filename Overview
troubleshooting/errors/400-bad-request.mdx Corrects partial-success behavior, but its unconditional retry-safety claim can lead callers to create duplicate events.
troubleshooting/errors/429-rate-limit-exceeded.mdx Correctly aligns /import and /track with the documented rolling 2GB-per-minute ingestion limit.
docs.json Adds the troubleshooting hub and all new pages to the FAQs navigation.

Reviews (5): Last reviewed commit: "Merge branch 'main' into copilot/tof-446..." | Re-trigger Greptile

Comment thread troubleshooting/errors/429-rate-limit-exceeded.mdx Outdated
Comment thread troubleshooting/errors/400-bad-request.mdx Outdated
The original pages documented behavior Mixpanel's API does not have.
Rewritten from openapi/ingestion.openapi.yaml and reference/import-events.mdx.

Corrected:
- Rate limit was "2GB per hour". It is 2GB of uncompressed JSON per
  minute, or ~30k events/sec on a rolling one-minute basis. The old
  figure would have made anyone throttle a backfill 60x too slowly.
- All five example bodies used "code": 0. Real responses return the HTTP
  status as code plus a status string; /import 400s also carry
  num_records_imported and per-record insert_id.
- The 429 page told readers to respect a Retry-After header. Mixpanel
  does not send one. The page now says so and gives the documented
  backoff: start 2s, double to 60s, 1-5s jitter.
- /import request limit was 2MB. It is 10MB uncompressed.
- Gzip was described as a way to avoid 413s. The limit is measured
  against the uncompressed body.
- Empty distinct_id was listed as a 400 cause. The docs instruct you to
  send an empty string for unattributed events; what is rejected is the
  placeholder list (anon, null, n/a, and so on).
- "Retry the batch one event at a time" contradicted the reference,
  which says not to retry 400s at all.

Removed:
- The 403 page described /import, which never returns 403 (the spec
  declares 200, 400, 401, 413, 429). Rescoped to /track, /engage, and
  /groups, which do, using the spec's ErrorResponse shape.
- An invented permission table using the org role "Member" for a
  project-level operation, and a nonexistent "user profiles are
  disabled" project setting.

Added the /track 5-day historical window, a common reason backfilled
events never appear.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rec #9 says to title pages with the verbatim strings developers paste
into AI assistants, seeded from the content backlog. The five HTTP
status pages were invented rather than sourced, so this adds pages for
what users actually search, drawn from the top three log clusters:

- Snowflake error 390144: JWT token is invalid (asked twice via MCP)
- Duplicate events appearing in reports ($insert_id semantics)
- Backfilled or historical events are not appearing (/track 5-day window)
- Server-side events with no logged-in user
- Duplicate or orphaned user profiles

Every claim is sourced from the repo, the OpenAPI specs, or Snowflake's
own documentation. Three things the logs show users asking are NOT
written up, because Mixpanel does not document them anywhere:
a $insert_id dedup window (no such window exists; the page explains the
real four-part key instead), a $user_id format rule, and GA4 identity
stitching.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rec #9's acceptance calls for a hub page alongside the nav entries.
Groups the ten pages by what the reader is holding: an API status code,
a data symptom, an identity problem, or a connector auth failure.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

**Do not blindly retry a 400.** Validation errors fail consistently and still count against your rate limit. Fix the payload first.

**Resend the corrected events.** Because `$insert_id` deduplicates, resending events that already landed is safe.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Retry can bypass deduplication

When a caller resends already-ingested records after regenerating $insert_id or recomputing time, the four-part deduplication key changes, causing duplicate events despite this unconditional safety guarantee.

Suggested change
**Resend the corrected events.** Because `$insert_id` deduplicates, resending events that already landed is safe.
**Resend the corrected events.** Resending events that already landed is safe only when `event`, `time`, `distinct_id`, and `$insert_id` remain identical, because all four fields form the deduplication key.

@tylergoerzen-mxp tylergoerzen-mxp changed the title TOF-446: Add per-error troubleshooting pages for top Mixpanel API errors TOF-446: Add per-error troubleshooting pages seeded from Ask-AI and MCP logs Aug 20, 2026
@tylergoerzen-mxp
tylergoerzen-mxp marked this pull request as ready for review August 20, 2026 07:59
@tylergoerzen-mxp
tylergoerzen-mxp requested review from a team as code owners August 20, 2026 08:00
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