swc-project/swc · error
`{module_specifier}` matched `{prefix}` (from tsconfig.paths
Error message
`{module_specifier}` matched `{prefix}` (from tsconfig.paths) but failed to resolve:
{errors:?} What it means
TsConfigResolver (tsc.rs) applies tsconfig `paths` patterns to a module specifier. When a pattern matches (prefix/wildcard), it substitutes the captured part into each substitution target and tries the inner resolver with the raw specifier, then './<replaced>' and '<replaced>' relative to baseUrl. If every candidate fails, it bails with this message, embedding the per-target resolution errors, so the specifier matched a paths mapping but none of the mapped destinations exist.
Source
Thrown at crates/swc_ecma_loader/src/resolvers/tsc.rs:296
info!(
"Using `{}` for `{}` because the length of the jsc.paths entry is \
1",
replaced, module_specifier
);
return Ok(Resolution {
slug: Some(
replaced
.split([std::path::MAIN_SEPARATOR, '/'])
.next_back()
.unwrap()
.into(),
),
filename: FileName::Real(replaced.into()),
});
}
}
bail!(
"`{module_specifier}` matched `{prefix}` (from tsconfig.paths) but failed \
to resolve:\n{errors:?}"
)
}
Pattern::Exact(from) => {
// Should be exactly matched
if module_specifier != from {
continue;
}
let tp = Path::new(&to[0]);
let slug = to[0]
.split([std::path::MAIN_SEPARATOR, '/'])
.next_back()
.filter(|&slug| slug != "index.ts" && slug != "index.tsx")
.map(|v| v.rsplit_once('.').map(|v| v.0).unwrap_or(v))
.map(From::from);
View on GitHub (pinned to 5176682b65)
Solutions
- Check each substitution target in the matched paths entry actually exists on disk relative to baseUrl (mind the './' prefixing and case sensitivity)
- Fix `baseUrl` in tsconfig so relative targets resolve from the intended root, or make targets absolute
- Add or correct the missing file the alias points to, or update the alias after directory renames
- Read the embedded per-target errors in the message: they tell you exactly which candidates the resolver attempted
Example fix
// before (tsconfig.json)
{ "baseUrl": "src", "paths": { "@/*": ["src/*"] } }
// '@/foo' -> tries src/src/foo -> fails
// after
{ "baseUrl": ".", "paths": { "@/*": ["src/*"] } }
// '@/foo' -> resolves ./src/foo.ts Defensive patterns
Strategy: try-catch
Validate before calling
// Verify every substitution target of the matched alias exists relative to baseUrl
import { existsSync } from 'node:fs';
import path from 'node:path';
function aliasTargetsExist(tsconfig, spec) {
for (const [pattern, targets] of Object.entries(tsconfig.compilerOptions.paths ?? {})) {
const prefix = pattern.split('*')[0];
if (spec.startsWith(prefix)) {
const rest = spec.slice(prefix.length);
const ok = targets.some((t) => existsSync(path.resolve(tsconfig.compilerOptions.baseUrl ?? '.', t.replace('*', rest))));
if (!ok) return false;
}
}
return true;
} Try / catch
try {
const resolved = tsResolver.resolve(base, spec);
} catch (e) {
if (e.message.includes('(from tsconfig.paths)')) {
// e.message lists every attempted target + inner errors; fix tsconfig or add the file
throw new Error(`tsconfig paths misconfigured for '${spec}': ${e.message}`);
}
throw e;
} Prevention
- After any directory rename, grep tsconfig paths entries and confirm targets exist
- Set baseUrl explicitly and test aliases with tsc --noEmit before bundling
- Keep one source of truth for aliases (tsconfig) and derive bundler aliases from it
When it happens
Trigger: tsconfig contains `paths: { "@/*": ["src/legacy/*"] } }` and an import like '@/foo' matches, but src/legacy/foo.ts does not exist (wrong baseUrl, moved directory, wrong casing, or target file truly missing). The `to.len() == 1` fallback only returns the replaced path directly when there is exactly one target; otherwise failure is fatal.
Common situations: baseUrl not set or pointing to the wrong directory so './replaced' resolves from the wrong root; paths aliases from a template not updated after a folder rename; monorepos where tsconfig lives in a package root but the build runs from the workspace root; multiple substitution targets where none exists; extension not covered by the resolver's substitution table.
Related errors
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/4e15619fee6435b3.
Report an issue: GitHub.