TOF-446: Add per-error troubleshooting pages seeded from Ask-AI and MCP logs - #179
TOF-446: Add per-error troubleshooting pages seeded from Ask-AI and MCP logs#179tylergoerzen-mxp with Copilot wants to merge 6 commits into
Conversation
Co-authored-by: tylergoerzen-mxp <259741734+tylergoerzen-mxp@users.noreply.github.com>
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
Confidence Score: 4/5The 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 Files Needing Attention: troubleshooting/errors/400-bad-request.mdx
|
| 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
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. |
There was a problem hiding this comment.
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.
| **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. |
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 windowreact native production events not showing token init trackautomaticeventsToday 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 codes —
400 Bad Request,401 Unauthorized,403 Forbidden,413 Payload Too Large,429 Too Many RequestsSeeded from the content backlog, drawn from the top three log clusters:
Snowflake error 390144: JWT token is invalid— cluster 7, warehouse connectorsDuplicate events appearing in reports— cluster 2,$insert_idsemanticsBackfilled or historical events are not appearing— cluster 2, the/track5-day windowServer-side events with no logged-in user— cluster 1, identityDuplicate or orphaned user profiles— cluster 1, identityPlus an
Error Troubleshootinghub 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.yamlandreference/import-events.mdx. What changed:/importrate limit is 2 GB per hour"code": 0codeplus astatusstring;/import400s also carrynum_records_importedand per-recordinsert_id.Retry-Afterheader/importrequest limit is 2 MBdistinct_idcauses a 400anon,null,n/a, …).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'sErrorResponseshape. 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
/track5-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:
$insert_iddeduplication window exists. The agent query assumes one. The real rule is an exact match onevent,time,distinct_id,$insert_id, with no time bound. The duplicate-events page corrects the premise; the reference-side gaps need an owner.$user_idformat guidance exists, and three nearby rules mislead anyone who searches for one.