jdx/mise · error
[monorepo].config_roots did not match any config roots
Error message
[monorepo].config_roots did not match any config roots
What it means
Monorepo config resolution matched zero directories for the glob patterns in [monorepo].config_roots. The patterns exist and are non-empty, but nothing on disk matches them, so mise cannot enumerate per-project config roots and aborts the monorepo operation.
Solutions
- Verify the glob patterns in [monorepo].config_roots match directories that actually contain mise config files
- Run from the actual monorepo root (patterns are expanded relative to monorepo_config.root)
- Check for typos or renamed directories and update the patterns
- Run with MISE_DEBUG=1 to see which roots were scanned
Example fix
// before [monorepo] config_roots = ["packages/*"] // after (repo restructured) [monorepo] config_roots = ["libs/*", "apps/*"]
Defensive patterns
Strategy: validation
Validate before calling
# verify each config_root pattern matches at least one dir with a mise config for pat in $(yq '.monorepo.config_roots[]' mise.toml); do ls -d $pat >/dev/null 2>&1 || echo "pattern $pat matches nothing" done
Type guard
// Rust
fn patterns_match_any(root: &Path, patterns: &[String]) -> bool {
patterns.iter().any(|p| glob_dir(root, p).next().is_some())
} Try / catch
// Rust
match config.monorepo_config_root_dirs() {
Ok(roots) => use(roots),
Err(e) if e.to_string().contains("did not match any config roots") => {
eprintln!("fix [monorepo].config_roots globs — no matches under monorepo root");
}
Err(e) => return Err(e),
} Prevention
- Keep config_roots patterns in sync with directory renames/restructures
- Verify patterns resolve relative to the monorepo root, not the cwd
- Test patterns with ls/glob before committing them
When it happens
Trigger: Calling monorepo_config_root_dirs (or its callers: monorepo_lockfile_root, monorepo_config_root_dirs_for_lockfiles, monorepo_config_root_dirs_with_filenames) when expand_config_root_dirs / expand_config_roots_with_filenames returns an empty vec — patterns match no existing subdirectories with configs.
Common situations: Typo'd or stale glob patterns (e.g. "packages/*" after restructuring to "libs/*"), patterns relative to the wrong monorepo root, or subdirectories present but containing no mise.toml/.mise.toml config.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- [bootstrap].config_roots did not match any config roots
- Cannot use :task syntax without a monorepo root
- Cargo workspace member pattern
- failed to discover workspace providers
- [monorepo].config_roots is required for monorepo operations
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/0e924ee52fbc8ebb.
Report an issue: GitHub.
Appendix: source
Thrown at src/config/mod.rs:888
) -> Result<Vec<PathBuf>> {
let monorepo_config = find_monorepo_config(&self.config_files)
.ok_or_else(|| eyre!("no config file in scope sets monorepo_root = true"))?;
let monorepo_root = monorepo_config.root;
let patterns = monorepo_config
.monorepo
.config_roots
.ok_or_else(|| eyre!("[monorepo].config_roots is required for monorepo operations"))?;
if patterns.is_empty() {
bail!("[monorepo].config_roots is required for monorepo operations");
}
let roots = match filenames {
Some(filenames) => {
expand_config_roots_with_filenames(&monorepo_root, &patterns, None, filenames)?
}
None => expand_config_root_dirs(&monorepo_root, &patterns, None)?,
};
if roots.is_empty() {
bail!("[monorepo].config_roots did not match any config roots");
}
Ok(roots)
}
pub(crate) async fn monorepo_union_tool_request_set(
self: &Arc<Self>,
) -> Result<ToolRequestSet> {
Ok(self.monorepo_union().await?.tool_request_set)
}
/// Loads the union plus the monorepo root directory's own effective
/// requests, for lockfile maintenance of the shared root lockfile.
///
/// `monorepo_union` merges the root's configs underneath each declared
/// config root, so a sibling's request for a short shadows the monorepo
/// root's own request for it. Treating the union as the set of live
/// requests for the root lockfile would then drop the root's request:
/// `mise lock --upgrade` migrated a v0 monorepo lockfile without bindingView on GitHub (pinned to 533346cc37)