fix(cohorts): return 400 for malformed legacy groups payload#70631
Merged
gustavohstrassburger merged 2 commits intoJul 24, 2026
masterPostHog/posthog:masterfrom
posthog-code/cohort-groups-400-validationPostHog/posthog:posthog-code/cohort-groups-400-validationCopy head branch name to clipboard
Merged
fix(cohorts): return 400 for malformed legacy groups payload#70631gustavohstrassburger merged 2 commits intomasterPostHog/posthog:masterfrom posthog-code/cohort-groups-400-validationPostHog/posthog:posthog-code/cohort-groups-400-validationCopy head branch name to clipboard
gustavohstrassburger merged 2 commits into
masterPostHog/posthog:masterfrom
posthog-code/cohort-groups-400-validationPostHog/posthog:posthog-code/cohort-groups-400-validationCopy head branch name to clipboard
Conversation
A legacy `groups` entry with none of properties/action_id/event_id raised an uncaught ValueError from Group.__init__, surfacing as an HTTP 500 out of the cohort create/update flow. Validate `groups` in CohortSerializer so bad input is rejected with a clean 400 instead. Generated-By: PostHog Code Task-Id: 3abb5c2c-c9e5-4e94-8093-ade2462739d2
Contributor
|
This PR hasn't seen activity in a week! Should it be merged, closed, or further worked on? If you want to keep it open, please remove the |
Contributor
🤖 CI reportℹ️ ClickHouse migration SQL — 1 migration(s)ClickHouse migration SQL per cloud environment
|
gustavohstrassburger
approved these changes
Jul 24, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Adds serializer-level validation for legacy cohort groups payloads so malformed input (previously raising a plain ValueError in Group.__init__) returns a client-facing HTTP 400 instead of an uncaught 500, and locks the behavior in with an endpoint test.
Changes:
- Added
CohortSerializer.validate_groupsto pre-validate legacygroupsentries by constructingGroup(**group)and convertingValueError/TypeErrorinto DRFValidationError. - Added an API test ensuring a malformed legacy group returns HTTP 400 with an explanatory message.
- Imported
Groupintoposthog/api/cohort.pyfor validation reuse.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| posthog/api/cohort.py | Adds serializer validation for legacy groups so malformed payloads return 400 instead of 500. |
| posthog/api/test/test_cohort.py | Adds regression test covering the malformed legacy groups payload case. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The validate_groups guard returned early on any falsy value, so an empty string or 0 skipped the type check and was persisted as-is, reintroducing the 500/corruption path the validation was meant to prevent. Guard on None only and include the failing group index in error messages. Generated-By: PostHog Code Task-Id: 5b1ff18d-e5b5-4978-837f-3978f6fc47f3
gustavohstrassburger
deleted the
posthog-code/cohort-groups-400-validation
branch
July 24, 2026 17:48
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
A malformed legacy
groupspayload in the cohort API threw an uncaughtValueErrorand returned a 500 instead of a clean 400.The create/update endpoint exposes the legacy
groupsfield onCohortSerializerwith no validation. When a request includes a group that has none ofproperties,action_id, orevent_id,CohortManager.createcallsGroup(**group), andGroup.__init__raises a plainValueError. DRF only convertsValidationErrorinto a 400, so this escaped as an HTTP 500 out ofperform_create. Low volume, but a real user-triggerable server error rather than a proper client-error response.Changes
Added a
validate_groupsmethod toCohortSerializerthat constructs each group throughGroup(...)and re-raises the resultingValueError/TypeErroras a DRFValidationError. Bad input now returns a 400 with a helpful message on both create and update.How did you test this code?
Added one endpoint test (
test_creating_cohort_with_malformed_group_returns_400) that posts a group missing all of properties/action_id/event_id and asserts a 400 — locking in the 500→400 fix; no existing test exercised the malformed-group path. Ranruff checkandruff format --check(both clean). The local sandbox lacks a fully provisioned Django/test runtime, so I was not able to execute the pytest suite here; the test should be run in CI.🤖 Agent context
Autonomy: Fully autonomous
Authored by PostHog Code (Claude Opus 4.8). Invoked the
/improving-drf-endpointsand/writing-testsskills while shaping the change. Chose field-levelvalidate_groupsreusing the realGroup(...)constructor over a hand-rolled key check, so the validation stays in lockstep with what creation actually accepts and also hardens the update path.Created with PostHog Code from an inbox report.