Community Note
- Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request.
- Please do not leave +1 or me too comments, they generate extra noise for issue followers and do not help prioritize the request.
- If you are interested in working on this issue or have submitted a pull request, please leave a comment.
Before submitting a bug report, we ask that you first search existing issues and pull requests to see if someone else may have experienced the same issue or may have already submitted a fix for it.
Python Version & Okta SDK Version(s)
Python 3.13.9
okta 3.4.4
pydantic 2.11.5
(Also reproduces on the versions any consumer currently pinned to okta==3.4.4 would be running; pydantic version is included here because it materially affects the exact error shape.)
Affected Class/Method(s)
okta.models.user_type_condition.UserTypeCondition
okta.models.access_policy_rule_conditions.AccessPolicyRuleConditions (embeds UserTypeCondition as user_type/userType)
okta.api.policy_api.PolicyApi.list_policy_rules (deserializes the 200 response to List[PolicyRule], and PolicyRule/AccessPolicyRule embed AccessPolicyRuleConditions)
okta.api_client.ApiClient.__deserialize (bulk-deserializes each list element with no per-item fallback, so one bad rule aborts the whole page)
Customer Information
Organization Name: withheld
This report reproduces entirely from synthetic payloads. No tenant data is required to confirm it.
Code Snippet
from okta.models.user_type_condition import UserTypeCondition
from okta.models.access_policy_rule import AccessPolicyRule
# 1. Minimal isolated repro
UserTypeCondition.from_dict({"exclude": None, "include": None})
# 2. Full synthetic policy-rule payload shaped like a real list_policy_rules() response
synthetic_rule = {
"id": "rul000000000000000000",
"name": "Example synthetic rule",
"status": "ACTIVE",
"priority": 1,
"system": False,
"created": "2026-01-01T00:00:00.000Z",
"lastUpdated": "2026-01-01T00:00:00.000Z",
"type": "ACCESS_POLICY",
"conditions": {
"network": {"connection": "ANYWHERE"},
"people": {
"users": {"exclude": [], "include": []},
"groups": {"exclude": [], "include": []},
},
"userType": {
"exclude": None,
"include": None,
},
},
"actions": {
"appSignOn": {
"access": "ALLOW",
"verificationMethod": {
"type": "ASSURANCE",
"factorMode": "1FA",
"reauthenticateIn": "PT2H",
},
}
},
}
AccessPolicyRule.from_dict(synthetic_rule)
In production this payload doesn't need to be constructed by hand. It is the shape returned by GET /api/v1/policies/{policyId}/rules for a rule whose conditions.userType is present but carries no explicit include/exclude list. That is the common case: a rule that doesn't filter by user type at all.
Debug Output / Traceback
Inlined rather than linked to a Gist so it stays reproducible from the issue body alone. All output below is copied verbatim from a real run against okta==3.4.4.
Case 1, minimal isolated repro:
2 validation errors for UserTypeCondition
exclude
Input should be a valid list [type=list_type, input_value=None, input_type=NoneType]
For further information visit https://errors.pydantic.dev/2.11/v/list_type
include
Input should be a valid list [type=list_type, input_value=None, input_type=NoneType]
For further information visit https://errors.pydantic.dev/2.11/v/list_type
Case 2, the full synthetic AccessPolicyRule.from_dict(...) payload. The same two errors bubble up unchanged. The outer AccessPolicyRuleConditions.user_type field is itself Optional, so the failure happens when the nested UserTypeCondition is constructed:
2 validation errors for UserTypeCondition
exclude
Input should be a valid list [type=list_type, input_value=None, input_type=NoneType]
For further information visit https://errors.pydantic.dev/2.11/v/list_type
include
Input should be a valid list [type=list_type, input_value=None, input_type=NoneType]
For further information visit https://errors.pydantic.dev/2.11/v/list_type
Control case: the identical rule with "userType": {"exclude": [], "include": []} (explicit empty lists instead of null) parses without error. The model itself is fine. Only the null case is broken:
SUCCESS. Parsed rule id: rul000000000000000000
userType condition: exclude=[] include=[]
Expected Behavior
list_policy_rules(policy_id) should return every rule on the policy, including rules whose conditions.userType block has null exclude/include arrays (i.e., rules that don't restrict on user type). A null array for an optional filter is ordinary, well-formed API output.
Actual Behavior
okta/models/user_type_condition.py (lines 40-41) declares both fields as required, non-nullable lists:
exclude: List[StrictStr] = Field(description="The user types to exclude")
include: List[StrictStr] = Field(description="The user types to include")
When the API returns "userType": {"exclude": null, "include": null} inside a rule's conditions, both fields fail pydantic validation (see traceback above). Because PolicyApi.list_policy_rules deserializes the whole page as List[PolicyRule] via ApiClient.__deserialize (okta/api_client.py, ~lines 450-466) with no per-item try/except, a single rule with a null userType block aborts deserialization of the entire page. Every other rule on that policy becomes unreachable through the SDK, not only the offending one.
This model is the outlier among its own siblings. Every other condition model in the same SDK that has the same exclude/include shape already marks both fields Optional with default=None:
| Model |
File |
Fields |
GroupCondition |
okta/models/group_condition.py:40-45 |
exclude/include: Optional[List[StrictStr]] = Field(default=None, ...) |
UserCondition |
okta/models/user_condition.py:40-45 |
same |
PolicyNetworkCondition |
okta/models/policy_network_condition.py:45-52 |
same |
PlatformPolicyRuleCondition |
okta/models/platform_policy_rule_condition.py:44-45 |
Optional[List[PlatformConditionEvaluatorPlatform]] = None |
UserTypeCondition (this bug) |
okta/models/user_type_condition.py:40-41 |
List[StrictStr], required, no default |
There's no behavioral reason UserTypeCondition should be stricter than GroupCondition or UserCondition. They are structurally identical include/exclude pairs used in the same AccessPolicyRuleConditions object, which points to an inconsistency in whichever OpenAPI Generator pass or hand-authored spec fragment produced this one model.
Two related models share the same root cause. Neither is the primary subject of this issue, and neither was confirmed against a live tenant, but both are structurally identical and worth fixing in the same pass if the spec is being touched:
okta/models/risk_detection_types_policy_rule_condition.py:43-48: exclude/include are required List[DetectedRiskEvents] with no default, the same pattern as this bug.
okta/models/user_identifier_policy_rule_condition.py:49: patterns: List[UserIdentifierConditionEvaluatorPattern] is a bare required annotation with no default at all, not even wrapped in Field(...).
Steps to reproduce
- Run the code snippet above with
okta==3.4.4, pydantic==2.11.5, Python 3.13.
- Observe the two
ValidationErrors for exclude/include on UserTypeCondition.
- Change
"userType": {"exclude": None, "include": None} to "userType": {"exclude": [], "include": []} in the same payload and re-run. It now succeeds, which isolates null as the cause rather than the model or the rest of the payload.
- Against a live tenant: call
GET /api/v1/policies/{accessPolicyId}/rules on any ACCESS_POLICY that has at least one rule not scoped by user type, then call the SDK's list_policy_rules(policy_id) for the same policy. The SDK call raises where the raw API call succeeds.
References
Community Note
Before submitting a bug report, we ask that you first search existing issues and pull requests to see if someone else may have experienced the same issue or may have already submitted a fix for it.
Python Version & Okta SDK Version(s)
(Also reproduces on the versions any consumer currently pinned to
okta==3.4.4would be running;pydanticversion is included here because it materially affects the exact error shape.)Affected Class/Method(s)
okta.models.user_type_condition.UserTypeConditionokta.models.access_policy_rule_conditions.AccessPolicyRuleConditions(embedsUserTypeConditionasuser_type/userType)okta.api.policy_api.PolicyApi.list_policy_rules(deserializes the 200 response toList[PolicyRule], andPolicyRule/AccessPolicyRuleembedAccessPolicyRuleConditions)okta.api_client.ApiClient.__deserialize(bulk-deserializes each list element with no per-item fallback, so one bad rule aborts the whole page)Customer Information
Organization Name: withheld
This report reproduces entirely from synthetic payloads. No tenant data is required to confirm it.
Code Snippet
In production this payload doesn't need to be constructed by hand. It is the shape returned by
GET /api/v1/policies/{policyId}/rulesfor a rule whoseconditions.userTypeis present but carries no explicit include/exclude list. That is the common case: a rule that doesn't filter by user type at all.Debug Output / Traceback
Inlined rather than linked to a Gist so it stays reproducible from the issue body alone. All output below is copied verbatim from a real run against
okta==3.4.4.Case 1, minimal isolated repro:
Case 2, the full synthetic
AccessPolicyRule.from_dict(...)payload. The same two errors bubble up unchanged. The outerAccessPolicyRuleConditions.user_typefield is itselfOptional, so the failure happens when the nestedUserTypeConditionis constructed:Control case: the identical rule with
"userType": {"exclude": [], "include": []}(explicit empty lists instead ofnull) parses without error. The model itself is fine. Only thenullcase is broken:Expected Behavior
list_policy_rules(policy_id)should return every rule on the policy, including rules whoseconditions.userTypeblock hasnullexclude/includearrays (i.e., rules that don't restrict on user type). Anullarray for an optional filter is ordinary, well-formed API output.Actual Behavior
okta/models/user_type_condition.py(lines 40-41) declares both fields as required, non-nullable lists:When the API returns
"userType": {"exclude": null, "include": null}inside a rule'sconditions, both fields fail pydantic validation (see traceback above). BecausePolicyApi.list_policy_rulesdeserializes the whole page asList[PolicyRule]viaApiClient.__deserialize(okta/api_client.py, ~lines 450-466) with no per-item try/except, a single rule with a nulluserTypeblock aborts deserialization of the entire page. Every other rule on that policy becomes unreachable through the SDK, not only the offending one.This model is the outlier among its own siblings. Every other condition model in the same SDK that has the same
exclude/includeshape already marks both fieldsOptionalwithdefault=None:GroupConditionokta/models/group_condition.py:40-45exclude/include:Optional[List[StrictStr]] = Field(default=None, ...)UserConditionokta/models/user_condition.py:40-45PolicyNetworkConditionokta/models/policy_network_condition.py:45-52PlatformPolicyRuleConditionokta/models/platform_policy_rule_condition.py:44-45Optional[List[PlatformConditionEvaluatorPlatform]] = NoneUserTypeCondition(this bug)okta/models/user_type_condition.py:40-41List[StrictStr], required, no defaultThere's no behavioral reason
UserTypeConditionshould be stricter thanGroupConditionorUserCondition. They are structurally identical include/exclude pairs used in the sameAccessPolicyRuleConditionsobject, which points to an inconsistency in whichever OpenAPI Generator pass or hand-authored spec fragment produced this one model.Two related models share the same root cause. Neither is the primary subject of this issue, and neither was confirmed against a live tenant, but both are structurally identical and worth fixing in the same pass if the spec is being touched:
okta/models/risk_detection_types_policy_rule_condition.py:43-48:exclude/includeare requiredList[DetectedRiskEvents]with no default, the same pattern as this bug.okta/models/user_identifier_policy_rule_condition.py:49:patterns: List[UserIdentifierConditionEvaluatorPattern]is a bare required annotation with no default at all, not even wrapped inField(...).Steps to reproduce
okta==3.4.4,pydantic==2.11.5, Python 3.13.ValidationErrors forexclude/includeonUserTypeCondition."userType": {"exclude": None, "include": None}to"userType": {"exclude": [], "include": []}in the same payload and re-run. It now succeeds, which isolatesnullas the cause rather than the model or the rest of the payload.GET /api/v1/policies/{accessPolicyId}/ruleson anyACCESS_POLICYthat has at least one rule not scoped by user type, then call the SDK'slist_policy_rules(policy_id)for the same policy. The SDK call raises where the raw API call succeeds.References
list_applicationsfails to deserialize responses when any SAML app omits required signOn fields #536 (closed): same defect family, overly strict required fields on a policy/app sub-model breaking bulk deserialization. Fixed forSamlApplicationSettingsSignOnby PR fix: remove required constraints from SamlApplicationSettingsSignOn schema #542.SamlApplicationSettingsSignOnschema." That PR touched both the generated Python model andopenapi/api.yaml'srequired:list, i.e. the actual fix belongs in the OpenAPI spec that generates these models (this file is explicitly marked# Do not edit the class manually.), not as a hand-patch to the generated.pyfile.SamlApplicationSettingsSignOn's five booleans are still required after fix: remove required constraints from SamlApplicationSettingsSignOn schema #542.list_policies/list_policy_rules; Completed Inline Hooks ITs #102 carries local workarounds for Implemented Features ITs #100/Completed Trusted Origins ITs #101 using the same "relax annotation +model_rebuild(force=True)" technique already used forLogSecurityContext.user_behaviorsin that repo.