fix(feature-flags): register evaluation context models#61051
Merged
Conversation
Django only registers models imported by an installed app's models package during app loading. The feature flags model package only imported TeamFeatureFlagDefaultsConfig, so FeatureFlagEvaluationContext could remain absent from the app registry until another request path imported it incidentally. The flag cache rebuild annotates on the flag_evaluation_contexts reverse relation. If that relation has not been registered, Django raises FieldError while rebuilding the cache after a feature flag save, including during experiment launch. Import the full feature flags model graph from models/__init__.py and add a regression test that verifies FeatureFlag can resolve the flag_evaluation_contexts reverse relation.
Contributor
|
Reviews (1): Last reviewed commit: "fix(feature-flags): register evaluation ..." | Re-trigger Greptile |
django-stubs's get_field plugin validates the string literal against statically-known fields and cannot see the flag_evaluation_contexts reverse relation (declared via related_name on FeatureFlagEvaluationContext), so it failed with [misc]. Assert the relation through _meta.related_objects instead, which avoids the plugin hook and matches the query name the cache annotation actually uses.
The test imported FeatureFlagEvaluationContext itself, so it could never observe the actual failure mode (the model absent from the app registry at django.setup() because nothing imported it). The runtime annotate path stays covered by the evaluation-context cache tests.
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
get_feature_flags()annotates on theflag_evaluation_contextsreverse relation when rebuilding the flag cache. Django only registers models that an app'smodelspackage imports at app-load time, butmodels/__init__.pyhere only re-exportedTeamFeatureFlagDefaultsConfig. SoFeatureFlagEvaluationContextwas registered only when some other path happened to import it first. In processes where that hadn't happened, saving a flag (e.g. during experiment launch) triggered the cache rebuild and raisedFieldError: Cannot resolve keyword 'flag_evaluation_contexts'.Error: https://us.posthog.com/error_tracking/019e8616-5f0c-7560-9634-78a259a27f6e
Changes
Re-export the full feature-flags model graph from
models/__init__.pyso every model is registered during app loading, rather than incidentally when another module happens to import it.How did you test this code?
Agent-assisted. Tested manually: confirmed via a fresh
django.setup()that theflag_evaluation_contextsreverse relation resolves and theget_feature_flags()annotation that was raisingFieldErrornow compiles. Existing evaluation-context cache tests still pass.🤖 Agent context
Claude Code (Opus 4.8) investigated the root cause and reviewed the fix. An initial narrower approach — a side-effect import in
feature_flag.py— was rejected in favor of registering the full model graph inmodels/__init__.py, the idiomatic Django fix that closes the gap for every model in the app, not just one path. Verified there's no app-load circular import: the core posthog app loads before product apps, and the feature-flags models only depend onposthog.*/django.*.