denoland/deno · error
No matching module graph roots found.
Error message
No matching module graph roots found.
What it means
`deno sync-types` (also invoked internally by `deno check`/setup for stock tsc) builds a module graph over explicit root patterns you passed to discover external specifiers. Roots that live under the DENO_DIR cache, or under node_modules/.deno relative to the project root, are filtered out to avoid graphing tens of thousands of dependency files. If you passed explicit roots and every one of them was filtered away, it bails with this message.
Source
Thrown at cli/tools/installer/local.rs:325
let roots: Vec<_> = roots
.into_iter()
.filter(|u| {
let Ok(path) = u.to_file_path() else {
return true;
};
if let Some(root) = &deno_dir_root
&& path.starts_with(root)
{
return false;
}
let rel = path.strip_prefix(&project_root).unwrap_or(&path);
!rel.components().any(|c| {
matches!(c.as_os_str().to_str(), Some("node_modules") | Some(".deno"))
})
})
.collect();
if has_explicit_roots && roots.is_empty() {
bail!("No matching module graph roots found.");
}
// Build the graph error-tolerantly: `create_graph_with_options` populates
// the graph and records unresolved modules as error entries without failing
// the whole build (unlike `check_specifiers`, which validates and discards
// everything on the first missing module). A real project always has some
// broken file (dead example scripts, etc.); we want every specifier that
// *did* resolve regardless.
let graph_creator = factory.module_graph_creator().await?;
// Silence warn-level diagnostics during this discovery build. It's an
// internal step (not the user's `deno check`), and the graph the user
// installed was already validated by `deno install` — re-emitting e.g.
// "workspace member ... was not used" warnings here is just noise.
let prev_log_level = log::max_level();
log::set_max_level(log::LevelFilter::Error);
let graph_result = graph_creator
.create_graph_with_options(crate::graph_util::CreateGraphOptions {
graph_kind: deno_graph::GraphKind::All,View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Point the roots at your own source files: `deno sync-types src/`
- If the project really lives under a directory named node_modules, move it or pass roots as file paths outside that tree
- Run `deno sync-types` with no roots to use '.' — the default project-wide discovery
Example fix
# before deno sync-types node_modules/left-pad # No matching module graph roots found. # after deno sync-types src/
Defensive patterns
Strategy: validation
Validate before calling
# pass roots that live in your own source tree: deno sync-types src/ # sanity check before scripting: ls src/*.ts >/dev/null || echo 'no project sources under src/'
Try / catch
Catch 'No matching module graph roots found'; retry `deno sync-types` with no root arguments (defaults to '.' over the project) — that path does not require the filter to keep anything.
Prevention
- Never point sync-types at node_modules/, .deno/, or DENO_DIR-managed trees
- Keep projects out of directories named node_modules
- Prefer the no-roots form `deno sync-types` for whole-project discovery
When it happens
Trigger: `deno sync-types <args>` where all matched files are inside node_modules/, a generated .deno/ dir, or DENO_DIR (e.g. `deno sync-types node_modules/...`, or a glob like `./vendor/**` that only matches filtered trees, or a project directory that itself sits under a path named node_modules).
Common situations: Pointing sync-types at installed dependencies instead of your own source; running from inside node_modules; overly broad globs whose only matches are generated/installed trees.
Related errors
- BenchContext::end() has already been invoked
- Bench attempted to exit with exit code: ${exitCode}
- Invalid type for fetch: must be a function
- Invalid type for onListen: must be a function
- ERR_PARSE_ARGS_INVALID_OPTION_VALUE
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/7ba82f6f9a4c721f.
Report an issue: GitHub.