nextlevelbuilder/ui-ux-pro-max-skill · error · ValueError

mode action must be dark or light

Error message

mode action must be dark or light

What it means

Actions with the mode: prefix accept exactly two values: "dark" or "light" (membership test against {"dark", "light"}). Any other string — "dark-mode", "Dark", "auto", "system" — raises this ValueError, because apply_decision_rules stores the value directly as the result's mode field which downstream design-system generation switches on.

Source

Thrown at src/ui-ux-pro-max/scripts/reasoning_contract.py:98

        for action in actions:
            _validate_action(action)
        if len(actions) != len(set(actions)):
            raise ValueError("{} contains duplicate actions".format(condition))
    return rules


def _validate_action(action):
    if not isinstance(action, str) or ":" not in action:
        raise ValueError("action must use a known prefix: {}".format(action))
    prefix, value = action.split(":", 1)
    if prefix not in ACTION_PREFIXES:
        raise ValueError("unknown decision-rule action: {}".format(action))
    if prefix in TOKEN_ACTION_PREFIXES and not TOKEN_RE.fullmatch(value):
        raise ValueError("invalid {} action value: {}".format(prefix, value))
    if prefix == "pattern" and not value.strip():
        raise ValueError("pattern action must name a pattern")
    if prefix == "mode" and value not in {"dark", "light"}:
        raise ValueError("mode action must be dark or light")


def apply_decision_rules(rules, query):
    """Return deterministic mutations and an audit trail; never execute data."""
    normalized = str(query or "").casefold()
    result = {"activated": [], "style_ids": [], "constraints": [],
              "pattern": None, "mode": None}
    for condition, actions in rules.items():
        active = condition == "must_have" or any(
            pattern.search(normalized)
            for pattern in CONDITION_PATTERNS.get(condition, ()))
        if not active:
            continue
        result["activated"].append({"condition": condition, "actions": list(actions)})
        for action in actions:
            prefix, value = action.split(":", 1)
            if prefix == "style" and value not in result["style_ids"]:
                result["style_ids"].append(value)

View on GitHub (pinned to a38d04c3d5)

Solutions

  1. Use exactly "mode:dark" or "mode:light" (lowercase).
  2. If conditional/auto theming is desired, encode it as separate if_ conditions (e.g. if_light_mode_needed already exists in the vocabulary) rather than a mode value.
  3. Case-normalize user input before composing rule JSON: value.lower().

Example fix

// before
{"if_mobile": ["mode:Dark", "mode:auto"]}

// after
{"if_mobile": ["mode:dark"]}
Defensive patterns

Strategy: validation

Validate before calling

VALID_MODES = {"dark", "light"}
for a in all_actions:
    prefix, _, value = a.partition(":")
    if prefix == "mode" and value not in VALID_MODES:
        raise ValueError(f"mode action must be dark or light; got {value!r}")

Type guard

def is_valid_mode_value(value: str) -> bool:
    return value in {"dark", "light"}

Prevention

When it happens

Trigger: _validate_action("mode:Dark") (case-sensitive), _validate_action("mode:auto"), _validate_action("mode:dark-mode") — inside any condition's action array passed to parse_decision_rules.

Common situations: Rules written from memory with common theme-toggle vocabulary ("auto", "system"); capitalization copied from prose docs.

Related errors


AI-assisted analysis of nextlevelbuilder/ui-ux-pro-max-skill@a38d04c3d5 (2026-08-14). Data as JSON: /api/errors/76f3dacb12f3b9a2. Report an issue: GitHub.