oxc-project/oxc · error · OxcDiagnostic

'{name}' is a compiler macro and can't be imported outside o

Error message

'{name}' is a compiler macro and can't be imported outside of `<script setup>`.

What it means

The second diagnostic of vue/no-import-compiler-macros: "'{name}' is a compiler macro and can't be imported outside of `<script setup>`." Compiler macros like `defineProps` only exist inside `<script setup>` blocks, where the SFC compiler transforms them. Importing them anywhere else (plain `<script>`, a .js module, a composable) produces code that calls a function which is not actually exported by 'vue' at that position, breaking the build at runtime or compile time.

Source

Thrown at crates/oxc_linter/src/rules/vue/no_import_compiler_macros.rs:18

use oxc_ast::{
    AstKind,
    ast::{ImportDeclarationSpecifier, ModuleExportName},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};

use crate::{AstNode, context::LintContext, frameworks::FrameworkOptions, rule::Rule};

fn no_import_compiler_macros_diagnostic(span: Span, name: &str) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!("'{name}' is a compiler macro and doesn't need to be imported."))
        .with_help("Remove the import statement for this macro.")
        .with_label(span)
}

fn invalid_import_compiler_macros_diagnostic(span: Span, name: &str) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!(
        "'{name}' is a compiler macro and can't be imported outside of `<script setup>`."
    ))
    .with_help("Remove the import statement for this macro.")
    .with_label(span)
}

#[derive(Debug, Default, Clone)]
pub struct NoImportCompilerMacros;

declare_oxc_lint!(
    /// ### What it does
    ///
    /// Disallow importing Vue compiler macros.
    ///
    /// ### Why is this bad?
    ///
    /// Compiler Macros like:
    /// - `defineProps`

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Remove the macro import — the code cannot use compiler macros outside `<script setup>`.
  2. Move the code that calls the macro (defineProps/defineEmits/...) back into the component's `<script setup>` block.
  3. Replace macro usage with runtime equivalents in plain modules, e.g. `defineComponent({ props: {...} })` or `vue`'s runtime `defineComponent` API.
  4. Re-run oxlint to confirm no remaining out-of-scope macro imports.

Example fix

// before (composables/useThing.ts)
import { defineProps } from 'vue'; // can't be imported outside of `<script setup>`
export function useThing(props) { ... }

// after (composables/useThing.ts)
export function useThing(props) { ... }
// and in the component:
<script setup>
const props = defineProps<{ id: string }>();
useThing(props);
</script>
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: An import declaration resolving a compiler macro name in any context other than `<script setup>` — e.g. `import { defineProps } from 'vue'` in a plain .ts composable, in a `<script>` block without `setup`, or in a helper module that calls the macro.

Common situations: Extracting part of a component's prop logic into a helper file; mixing `<script>` and `<script setup>` and importing the macro in the wrong block; copy-pasting script-setup code into a plain module.

Related errors


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