swc-project/swc · error
`paths.{from}` should have only one wildcard
Error message
`paths.{from}` should have only one wildcard What it means
When building the import resolver from tsconfig.json, each `paths` mapping key may contain at most one `*` wildcard: the resolver models the key as a literal prefix plus a single Pattern::Wildcard. A key containing two or more `*` characters panics during TsconfigResolver construction. This mirrors TypeScript's own rule that paths patterns allow one wildcard.
Source
Thrown at crates/swc_ecma_loader/src/resolvers/tsc.rs:77
#[cfg(debug_assertions)]
info!(
base_url = tracing::field::display(base_url.display()),
"jsc.paths"
);
}
let mut paths: Vec<(Pattern, Vec<String>)> = paths
.into_iter()
.map(|(from, to)| {
assert!(
!to.is_empty(),
"value of `paths.{from}` should not be an empty array",
);
let pos = from.as_bytes().iter().position(|&c| c == b'*');
let pat = if from.contains('*') {
if from.as_bytes().iter().rposition(|&c| c == b'*') != pos {
panic!("`paths.{from}` should have only one wildcard")
}
Pattern::Wildcard {
prefix: from[..pos.unwrap()].to_string(),
}
} else {
assert_eq!(
to.len(),
1,
"value of `paths.{from}` should be an array with one element because the \
src path does not contains * (wildcard)",
);
Pattern::Exact(from)
};
(pat, to)
})View on GitHub (pinned to 5176682b65)
Solutions
- Rewrite the offending paths key so it contains exactly one `*` (e.g. "utils/*" instead of "utils/*/*")
- Split one multi-wildcard entry into several entries, each anchored on a distinct literal prefix
- Run tsc against the same tsconfig as a sanity check; TypeScript rejects multi-wildcard paths keys too
- Add a startup assertion that scans paths keys for wildcard count before building the resolver
Example fix
// tsconfig.json - before
"paths": {
"utils/*/*": ["src/utils/*/*"]
}
// tsconfig.json - after
"paths": {
"utils/*": ["src/utils/*"],
"utils/deep/*": ["src/utils/deep/*"]
} Defensive patterns
Strategy: validation
Validate before calling
// JS: validate tsconfig paths before building the SWC resolver
function validatePaths(tsconfig) {
for (const key of Object.keys(tsconfig.compilerOptions?.paths ?? {})) {
const wildcards = [...key].filter(c => c === '*').length;
if (wildcards > 1) {
throw new Error(`paths key "${key}" has ${wildcards} wildcards; only one is allowed`);
}
}
} Prevention
- Run `tsc --noEmit` on the same tsconfig to catch invalid paths patterns early
- Never generate paths keys from glob templates with multiple stars
- Add the wildcard-count check to config validation in CI
When it happens
Trigger: Constructing NodeImportResolver/TsconfigResolver with a tsconfig.json whose compilerOptions.paths contains a key like "utils/*/*"; the code finds the first `*` with position() and the last with rposition() and panics when they differ.
Common situations: Monorepo tsconfig files with nested wildcard patterns, configs hand-migrated from webpack/glob-style tooling, generating tsconfig programmatically with glob templates, invalid tsconfig passing a plain tsc check but never exercised for those paths.
Related errors
- Please specify `filename`
- Error occurred while loading config file at ${config}: ${e}
- {} is not a valid expression
- failed to parse `global_defs.{k}` of minifier options: {err:
- Value of `global_defs.{k}` must be a string literal:
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/d2c71d731ad84f7e.
Report an issue: GitHub.