apache/superset · error · ValidationError
Regular RLS filters require at least one subject.
Error message
Regular RLS filters require at least one subject.
What it means
ValidationError raised in UpdateRLSRuleCommand.validate when the effective filter_type (payload value or the rule's stored value) resolves to REGULAR while the effective subjects list (payload 'subjects' or the rule's existing bindings) is empty — a regular RLS filter must keep at least one subject.
Source
Thrown at superset/commands/security/update.py:114
# in the request body. A partial update (e.g. changing only the name)
# must leave the rule's existing tables/subjects bindings untouched
# rather than replacing them with empty lists.
if "subjects" in self._properties:
subjects = populate_subject_list(
self._subjects,
default_to_user=False,
)
self._properties["subjects"] = subjects
else:
subjects = list(self._model.subjects)
filter_type = self._properties.get("filter_type", self._model.filter_type)
filter_type_value = getattr(filter_type, "value", filter_type)
if (
filter_type_value == RowLevelSecurityFilterType.REGULAR.value
and not subjects
):
raise ValidationError(
{"subjects": ["Regular RLS filters require at least one subject."]}
)
View on GitHub (pinned to f4587218dd)
Solutions
- Include a non-empty 'subjects' array in the same PUT (e.g. a role subject) whenever filter_type is Regular
- Alternatively switch filter_type to 'Base' if the clause must be subject-independent
- Read the rule first (GET) to know the stored subjects/type your partial update will combine with
Example fix
# before
client.put(url, json={'filter_type': 'Regular'}) # rule has no subjects
# after
client.put(url, json={'filter_type': 'Regular',
'subjects': [{'subject_type': 'Role', 'subject': 'Gamma'}]}) Defensive patterns
Strategy: validation
Validate before calling
eff_type = props.get('filter_type', stored_rule['filter_type'])
eff_subjects = props['subjects'] if 'subjects' in props else stored_rule['subjects']
if eff_type == 'Regular':
assert eff_subjects, 'Regular rules need >=1 subject' Type guard
def update_keeps_regular_subjects(props: dict, stored: dict) -> bool:
ftype = props.get('filter_type', stored.get('filter_type'))
ftype = getattr(ftype, 'value', ftype)
subjects = props['subjects'] if 'subjects' in props else stored.get('subjects', [])
return ftype != 'Regular' or bool(subjects) Try / catch
from superset.commands.exceptions import ValidationError
try:
UpdateRLSRuleCommand(rid, props).run()
except ValidationError as e:
if 'subjects' in e.normalized_messages():
props['subjects'] = [{'subject_type': 'Role', 'subject': 'Gamma'}]
UpdateRLSRuleCommand(rid, props).run() Prevention
- GET the rule first so partial updates merge against known stored values
- Never send 'subjects': [] on a Regular rule
- Pair any filter_type change with an explicit subjects payload
When it happens
Trigger: PUT switching filter_type to 'Regular' on a rule with no subjects; PUT with 'subjects': [] on a Regular rule; a partial update that only changes filter_type while the stored rule has no subject bindings (subjects then default to the empty stored list).
Common situations: Promoting a Base filter to Regular without adding subjects; clearing subjects to 'reset' a rule; partial payloads whose defaults surprise the author.
Related errors
- Regular RLS filters require at least one subject.
- Datasource does not exist
- Subjects are invalid
- Unsupported whisker type: ${whiskerOptions}
- Found invalid orderby options
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/5156cc0768acf8f9.
Report an issue: GitHub.