fix(data-imports): shrink Anthropic usage report page size to avoid 400 - #70812
Merged
Merged
Conversation
The usage_report endpoint grouped by all eight dimensions while requesting the 31-bucket daily maximum. On a full-refresh backfill that overflows the report's per-response result cap and Anthropic returns a 400, failing the sync. Drop the page size to the API default of 7 buckets. This keeps each response under the cap while pagination still walks all history and every group_by dimension is preserved. Generated-By: PostHog Code Task-Id: e0ed6ad8-be66-49ec-a829-0786fabdfb06
Contributor
|
Hey @Gilbert09! 👋 It looks like your git author email on this PR isn't your
You can fix it for this repo with: git config user.email "you@posthog.com"Or set it globally with |
There was a problem hiding this comment.
Trivial, well-tested pagination limit fix by an owning-team author with strong familiarity; no risky territory touched.
- Author wrote 100% of the modified lines and has 3 merged PRs in these paths (familiarity STRONG).
- 👍 on the PR from hex-security-app[bot].
Gate mechanics and policy version
| Gate | Result | |
|---|---|---|
| prerequisites | ✓ | all clear |
| deny-list | ✓ | no deny categories matched |
| size | ✓ | 5L, 1F substantive, 16L/2F incl. docs/generated/snapshots — within ceiling |
| tier | ✓ | T1-agent / T1a-trivial (16L, 2F, single-area, fix) |
| stamphog 2.0.0b3 | .stamphog/policy.yml @ 4a9b203 · reviewed head 56cf70e |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The Anthropic data warehouse source is failing on the messages usage report with a
400 Client Error: Bad Requestfrom/v1/organizations/usage_report/messages. It surfaced in error tracking firing across several teams' syncs at once (issue019f61a0-5d7f-7091-889a-0304928cbd3e), raised from_fetch_pagein the Anthropic source.The request itself is well-formed: every
group_by[]value we send is documented as valid,bucket_width=1dis valid, andstarting_atis a valid RFC 3339 timestamp. So this is not a credential problem (those come back as 401/403 and are already treated as non-retryable) and not a single bad param.The distinguishing factor is response size.
usage_reportgroups by all eight dimensions and asks forlimit=31, the maximum number of daily buckets. Grouping by every dimension multiplies the result rows per bucket, and 31 dense historical buckets per page pushes the response past the report's per-response result cap, which the API rejects with a 400. This bites on the initial full-refresh backfill (starting_at= the Anthropic launch date), where every page is packed with historical buckets. Incremental runs return only a handful of buckets regardless oflimit, so they stay under the cap.cost_report, which groups by two low-cardinality dimensions and uses the API default page size, is unaffected.Anthropic's own guidance for this 400 is to reduce the number of
group_bydimensions or narrow the time range / bucket count. Pagination on this endpoint is per bucket via anext_pagecursor, so the cap is per response.Changes
Drop the
usage_reportpage size from the 31-bucket max to the API default of 7. Each response now carries fewer buckets and stays under the result cap, while pagination vianext_pagestill walks all history and everygroup_bydimension is preserved. This mirrors whatcost_reportalready does.This is the least-lossy fix available: it changes only pagination granularity, never the data returned. Very large organizations could in theory still exceed the cap even at 7 buckets, in which case a follow-up would trim the highest-cardinality
group_bydimensions, but that permanently drops breakdown fidelity so it is not worth doing preemptively.How did you test this code?
Automated tests only (I am Claude, an agent; I did not run a live backfill against the Anthropic API).
TestReportParams.test_incremental_uses_watermark_as_starting_atto expect the new page size.TestReportParams.test_usage_report_page_size_stays_below_bucket_max, which asserts the endpoint still groups by the full eight-dimension set while capping the page size. This catches the specific regression of someone bumpinglimitback to the 31-bucket max under the full group_by, which is what triggers the 400.pytest .../sources/anthropic/tests/test_anthropic.py— 28 passed. Ranruff checkandruff format --checkon both changed files — clean.🤖 Agent context
Autonomy: Fully autonomous
Triaged from the error-tracking issue above. I (Claude) pulled the stack trace and representative events via the PostHog error-tracking tools, read the Anthropic source under
products/warehouse_sources/backend/temporal/data_imports/sources/anthropic/, and cross-checked the request against Anthropic's current Usage & Cost Admin API docs to confirm every param we send is individually valid.Decision: classified this as a fixable request-construction bug rather than a user/upstream error. A 400 on a request we fully control, firing for every affected org at once, is our bug, not a per-customer credential or data issue, so extending
NonRetryableErrorswould have masked it and permanently disabled the syncs. I considered trimming thegroup_byset instead, but reducing the page size is strictly less lossy (no dimension is dropped) and is one of Anthropic's recommended remedies for this error. Verified no open PR already covers this: #70811 touches the same source but handles 429Retry-Afterinanthropic.py, a different root cause and different file.Created with PostHog Code