oxc-project/oxc · error

invalid fix kind: {s}. Valid fix kinds are fix, suggestion,

Error message

invalid fix kind: {s}. Valid fix kinds are fix, suggestion, or dangerous.

What it means

Diagnostic from oxlint's vue/valid-define-emits rule (crates/oxc_linter/src/rules/vue/valid_define_emits.rs), `<script setup>` blocks only. It reports a `defineEmits` call that supplies both a literal type parameter and a runtime argument. The two declarations compete: the type parameter is the source of truth for inference while the argument overrides runtime options, degrading types and confusing readers.

Source

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

        })
        .unique()
        .map(parse_fix_kind)
        .reduce(|acc, kind| quote! { #acc.union(#kind) })
        .expect("No fix kinds were found during parsing, but at least one is required.");

    if is_conditional {
        quote! { RuleFixMeta::Conditional(#fix_kinds) }
    } else {
        quote! { RuleFixMeta::Fixable(#fix_kinds) }
    }
}

fn parse_fix_kind(s: &str) -> proc_macro2::TokenStream {
    match s {
        "fix" | "fixes" => quote! { FixKind::Fix },
        "suggestion" | "suggestions" => quote! { FixKind::Suggestion },
        "dangerous" => quote! { FixKind::Dangerous },
        _ => panic!("invalid fix kind: {s}. Valid fix kinds are fix, suggestion, or dangerous."),
    }
}

View on GitHub (pinned to a3d33dda7c)

Solutions

  1. Delete the runtime argument: `defineEmits<(e: 'notify') => void>()`.
  2. Or drop the type parameter and keep one fully typed runtime object with validator functions.
  3. Keep exactly one declaration style per component.

Example fix

// before
const emit = defineEmits<(e: 'notify') => void>({ submit: null });

// after
const emit = defineEmits<(e: 'notify') => void>();
Defensive patterns

Strategy: validation

Validate before calling

// reject defineEmits calls carrying both a type parameter and an argument
const re = /defineEmits\s*(<[^>]*>)?\s*\(([^)]*)\)/g;
for (const m of setupSource.matchAll(re)) {
  if (m[1] && m[2].trim()) {
    throw new Error('defineEmits: remove the argument when a type parameter is given');
  }
}

Prevention

When it happens

Trigger: `defineEmits<(e: 'notify') => void>({ submit: null })` in a `<script setup lang="ts">` block — type_arguments present AND at least one argument passed. The help text says to remove the argument for better type inference.

Common situations: Incrementally typing JS components to TS and leaving the old object argument behind; copy-paste combining both declaration styles; codemods adding type parameters without removing arguments.

Related errors


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