oxc-project/oxc · error · OxcDiagnostic
Props are defined in both `defineProps` and `export default
Error message
Props are defined in both `defineProps` and `export default {}`. What it means
Diagnostic from the oxlint rule `vue/valid-define-props`. Before scanning calls, the rule computes `has_other_script_emits = has_default_exports_property(&ctx.other_file_hosts(), "props")` — true when a sibling plain `<script>` block exports a default object containing a `props` property. If `defineProps` also declares props in `<script setup>`, the helper returns `DefineMacroProblem::DefineInBoth`. Declaring props twice makes the two declarations compete and the compiled component's props become ambiguous.
Source
Thrown at crates/oxc_linter/src/rules/vue/valid_define_props.rs:41
span.label("`defineProps` is called here"),
second_span.label("`defineProps` is called here too"),
])
}
fn events_not_defined(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Props are not defined.")
.with_help("Define at least one prop in `defineProps`.")
.with_label(span)
}
fn referencing_locally(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("`defineProps` is referencing locally declared variables.")
.with_help("inline the variable or import it from another module.")
.with_label(span)
}
fn define_in_both(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Props are defined in both `defineProps` and `export default {}`.")
.with_help("Remove `export default`.")
.with_label(span)
}
#[derive(Debug, Default, Clone)]
pub struct ValidDefineProps;
declare_oxc_lint!(
/// ### What it does
///
/// Enforce valid usage of the `defineProps` compiler macro in Vue.
///
/// This rule reports `defineProps` compiler macros in the following cases:
///
/// - `defineProps` is referencing locally declared variables.
/// - `defineProps` has both a literal type and an argument. e.g. `defineProps<{ /*props*/ }>({ /*props*/ })`
/// - `defineProps` has been called multiple times.
/// - Props are defined in both `defineProps` and `export default {}`.View on GitHub (pinned to e1e7af627c)
Solutions
- Remove the `export default {}` from the plain `<script>` block (help text: 'Remove `export default`') and keep props solely in `defineProps`.
- Alternatively keep `export default { props: {...} }` and delete the `defineProps` call — but never both.
- After removing, re-run lint: the companion 'Props are not defined' diagnostic also disappears only if one declaration remains.
Example fix
// before
<script>
export default { props: { msg: String } }
</script>
<script setup>
defineProps({ count: Number })
</script>
// after
<script setup>
defineProps({ msg: String, count: Number })
</script> Defensive patterns
Strategy: validation
Validate before calling
const bothWays =
/export\s+default\s*\{[\s\S]*?\bprops\s*:/.test(src) &&
/\bdefineProps\s*[(<]/.test(setup);
if (bothWays) {
throw new Error('Props declared both in export default {} and defineProps — remove one');
} Prevention
- Finish Options API → script setup migrations: remove export default { props } once defineProps exists.
- Lint .vue files with vue/valid-define-props in CI to catch half-migrated files.
When it happens
Trigger: A .vue file (VueSetup) that has BOTH `<script> export default { props: { msg: String } } </script>` AND a `defineProps({ count: Number })` in `<script setup>`. Any `defineProps` call with a declaration (argument or type parameter) while the sibling `export default {}` has a `props` key triggers it; the diagnostic span is the `defineProps` call.
Common situations: Partial migration from Options API where `export default { props }` was left behind after adding `defineProps`; mixing both styles in one file because examples were combined; tooling that injects `defineProps` into files that still declare props the old way.
Related errors
- TS5081
- `defineOptions()` cannot be used to declare `{prop_name}`. U
- `defineProps` has both a type-only emit and an argument.
- `defineProps` has been called multiple times.
- Props are not defined.
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/8a3d319d1fb2212b.
Report an issue: GitHub.