oxc-project/oxc · error

invalid fix capabilities: {invalid}. Valid capabilities are

Error message

invalid fix capabilities: {invalid}. Valid capabilities are none, pending, fix, suggestion, or [fix|suggestion]_[conditional?]_[dangerous?].

What it means

The second diagnostic of oxlint's vue/return-in-emits-validator rule (crates/oxc_linter/src/rules/vue/return_in_emits_validator.rs). It fires when the validator does return values, but every returned expression is statically falsy — `false`, `0`, `null`, `''`, `undefined`, `NaN`, or `0n` literals (checked by is_falsy). Such a validator always rejects the event, which almost always signals placeholder or inverted logic rather than intent.

Source

Thrown at crates/oxc_macros/src/declare_oxc_lint.rs:426

    const SEP: char = '_';

    match s {
        "none" => {
            return quote! { RuleFixMeta::None };
        }
        "pending" => {
            return quote! { RuleFixMeta::FixPending };
        }
        "fix" => return quote! { RuleFixMeta::Fixable(FixKind::SafeFix) },
        "suggestion" => return quote! { RuleFixMeta::Fixable(FixKind::Suggestion) },
        "conditional" => {
            panic!("Invalid fix capabilities: missing a fix kind. Did you mean 'fix-conditional'?")
        }
        "None" => panic!("Invalid fix capabilities. Did you mean 'none'?"),
        "Pending" => panic!("Invalid fix capabilities. Did you mean 'pending'?"),
        "Fix" => panic!("Invalid fix capabilities. Did you mean 'fix'?"),
        "Suggestion" => panic!("Invalid fix capabilities. Did you mean 'suggestion'?"),
        invalid if !invalid.contains(SEP) => panic!(
            "invalid fix capabilities: {invalid}. Valid capabilities are none, pending, fix, suggestion, or [fix|suggestion]_[conditional?]_[dangerous?]."
        ),
        _ => {}
    }

    assert!(s.contains(SEP));

    let mut is_conditional = false;
    let fix_kinds = s
        .split(SEP)
        .filter(|seg| match *seg {
            "conditional" => {
                is_conditional = true;
                false
            }
            // e.g. "safe_fix". safe is implied
            "safe"
            // e.g. fix_or_suggestion

View on GitHub (pinned to a3d33dda7c)

Solutions

  1. Return the actual validation expression instead of a literal: `return payload.length > 0;`.
  2. Replace stubs with real checks before merging; use `return true` only for deliberately permissive validators.
  3. If always-reject is truly intended, disable the rule for that validator with a comment explaining why.

Example fix

// before
emits: { foo: () => false }

// after
emits: { foo: (payload) => payload !== null }
Defensive patterns

Strategy: validation

Validate before calling

// validators must not return only falsy literals
function checkEmits(defs) {
  for (const [name, v] of Object.entries(defs)) {
    if (typeof v !== 'function') continue;
    if (/\breturn\s+(false|0|null|''|undefined|NaN|0n)\s*[;\n]/.test(v.toString())) {
      throw new Error(`validator '${name}' returns only falsy literals`);
    }
  }
}

Prevention

When it happens

Trigger: `emits: { foo: () => false }`, or a body whose returns are all falsy literals across branches (`if (a) return false; else if (b) return 0;`). One return of a non-literal expression (variable, comparison) anywhere silences the rule because it could be truthy.

Common situations: Stub validators left from scaffolding (`return false` TODO); inverted conditions; returning literal results of side-effect calls that were inlined.

Related errors


AI-assisted analysis of oxc-project/oxc@a3d33dda7c (2026-08-20). Data as JSON: /api/errors/208b204eeffef03c. Report an issue: GitHub.