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
- Delete the runtime argument: `defineEmits<(e: 'notify') => void>()`.
- Or drop the type parameter and keep one fully typed runtime object with validator functions.
- 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
- Pick one declaration style per component: type-only or runtime object, never both.
- When adding a type parameter during TS migration, delete the old runtime argument in the same commit.
- Review defineEmits diffs — single-line macro changes are easy to verify.
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
- [HIRBuilder] expected block {:?} to exist
- Inline helpers are not supported yet
- TS5042
- TS5081
- Use type-based declaration instead of runtime declaration
AI-assisted analysis of oxc-project/oxc@a3d33dda7c (2026-08-20).
Data as JSON: /api/errors/ccb008377ee6c663.
Report an issue: GitHub.