oxc-project/oxc · error · anyhow::Error
TS5042
TS5042
Error message
Option 'project' cannot be mixed with source files on a command line.
What it means
Diagnostic from oxlint's vue/valid-define-emits rule (crates/oxc_linter/src/rules/vue/valid_define_emits.rs). It fires when the `defineEmits` argument references a variable declared locally in the same `<script setup>` scope (`const def = {...}; defineEmits(def)`). Compiler macros are hoisted and transformed at compile time, so referencing setup-local values can break compilation or produce wrong output. Variables imported from other modules, or declared in the sibling plain `<script>` block, are fine.
Source
Thrown at crates/oxc_type_checker/src/execute/tsc.rs:75
for file in program.files() {
println!(" {}", file.file_name().display());
}
println!("({} files)", program.len());
Ok(())
}
/// Resolve the command line into the `tsconfig.json` (or config file) to load, mirroring
/// the project-resolution block of tsgo's `tscCompilation`.
///
/// Returns:
/// - `Ok(Some(path))` — a resolved config file to load,
/// - `Ok(None)` — source files were given with no config file (compile them directly),
/// - `Err(_)` — one of `tsc`'s command-line errors, ready to print.
fn resolve_config_file(command: &TypeCheckCommand, cwd: &Path) -> Result<Option<PathBuf>> {
if let Some(project) = &command.project {
// TS5042
if !command.files.is_empty() {
bail!("Option 'project' cannot be mixed with source files on a command line.");
}
let file_or_directory = to_path(cwd, project);
if file_or_directory.is_dir() {
// A directory: look for `tsconfig.json` inside it.
let config_file = file_or_directory.join("tsconfig.json");
if config_file.is_file() {
Ok(Some(config_file))
} else {
// TS5081
bail!(
"Cannot find a tsconfig.json file at the current directory: {}.",
config_file.display()
);
}
} else if file_or_directory.exists() {
// An explicit config file (need not be named `tsconfig.json`).
Ok(Some(file_or_directory))View on GitHub (pinned to e1e7af627c)
Solutions
- Inline the object/array literal into the call: `defineEmits({ notify: null })`.
- Or move the definition to a module and import it: `import { emitsDef } from './defs'; defineEmits(emitsDef);`.
- In TS prefer a type-only declaration: `defineEmits<(e: 'notify') => void>()`.
Example fix
// before
const def = { notify: null };
defineEmits(def);
// after
import { def } from './emits-defs';
defineEmits(def);
// or simply: defineEmits({ notify: null }) Defensive patterns
Strategy: validation
Validate before calling
// defineEmits must not reference setup-local variables
if (/const\s+(\w+)[\s\S]*?defineEmits\s*\(\s*\1\s*\)/.test(setupSource)) {
throw new Error('defineEmits references a locally declared variable; inline it or import it');
} Prevention
- Pass literals (object/array) or type parameters directly to compiler macros.
- Shared definitions belong in a separate module, imported.
- Remember macros are compile-time hoisted; never feed them setup-local state.
When it happens
Trigger: `<script setup> const def = { notify: null }; defineEmits(def) </script>` — the argument identifier resolves to a binding declared inside the setup scope. The identical code with `def` imported from './defs' or declared in a normal `<script>` block passes the rule.
Common situations: Sharing props/emits definition objects between components via copy-paste; extracting the object 'for readability' inside the setup block.
Related errors
- [HIRBuilder] expected block {:?} to exist
- Inline helpers are not supported yet
- TS5081
- invalid fix kind: {s}. Valid fix kinds are fix, suggestion,
- `defineOptions()` cannot be used to declare `{prop_name}`. U
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/cc07a42bb64ca9c4.
Report an issue: GitHub.