oxc-project/oxc · error · OxcDiagnostic
`defineProps` is referencing locally declared variables.
Error message
`defineProps` is referencing locally declared variables.
What it means
Diagnostic from the oxlint rule `vue/valid-define-props`. When `check_define_macro_call_expression` detects that the argument to `defineProps` references identifiers declared locally in the same `<script setup>` block (as opposed to imports or a sibling `<script>` binding), it returns `DefineMacroProblem::ReferencingLocally`. The Vue compiler cannot statically resolve local variables into the props definition, so the component's props may break silently or be typed incorrectly.
Source
Thrown at crates/oxc_linter/src/rules/vue/valid_define_props.rs:35
}
fn called_multiple_times(span: Span, second_span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("`defineProps` has been called multiple times.")
.with_help("combine all `defineProps` calls into a single `defineProps` call.")
.with_labels([
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.
///View on GitHub (pinned to e1e7af627c)
Solutions
- Inline the object: `defineProps({ msg: String })`.
- Move the definition into a plain `<script>` block (sibling to `<script setup>`) or another module and import it, as the help text suggests.
- Use `// oxlint-disable vue/valid-define-props` on the line only if you have verified the compiler accepts your specific case.
Example fix
// before
<script setup>
const def = { msg: String }
defineProps(def)
</script>
// after
<script setup>
defineProps({ msg: String })
</script> Defensive patterns
Strategy: validation
Validate before calling
const arg = setup.match(/\bdefineProps\s*\(\s*([a-zA-Z_$][\w$]*)\s*\)\s*;?/);
if (arg && new RegExp(`(?:const|let|var)\\s+${arg[1]}`).test(setup)) {
throw new Error(`defineProps references local variable '${arg[1]}' — inline it or import it`);
} Prevention
- Inline prop definitions or move them to a plain <script> block / separate module.
- Keep type-level references (PropType<typeof x>) — those are fine; only runtime value references are checked.
When it happens
Trigger: `const def = { msg: String }; defineProps(def)` inside `<script setup>` — the argument expression contains an IdentifierReference bound in the same block rather than imported or declared in a sibling `<script>`. The pass tests show allowed shapes: `const def` in plain `<script>` then `defineProps(def)` in `<script setup>`, `import { propsDef } from './defs'; defineProps(propsDef)`, and type-level references like `Array as PropType<typeof strList>` (type positions are not checked).
Common situations: Reusing a shared prop-shape object defined in the same file; grouping prop definitions into a `const` for readability; converting Options API `props: def` directly into `defineProps(def)` without moving `def`.
Related errors
- `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.
- Props are defined in both `defineProps` and `export default
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/2102928f08bbb235.
Report an issue: GitHub.