{"record":{"id":"192c815295e025d2","repo":"jdx/mise","slug":"monorepo-config-roots-is-required-for-monorepo-o","errorCode":null,"errorMessage":"[monorepo].config_roots is required for monorepo operations","messagePattern":"\\[monorepo\\]\\.config_roots is required for monorepo operations","errorType":"validation","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/config/mod.rs","lineNumber":783,"sourceCode":"    ///\n    /// `None` matches any existing directory and is used for lockfile migration\n    /// and routing. `Some(filenames)` requires a recognized config or idiomatic\n    /// version file and is used for full monorepo union/task loading.\n    pub(crate) fn monorepo_config_root_dirs(\n        &self,\n        filenames: Option<&[String]>,\n    ) -> Result<Vec<PathBuf>> {\n        let monorepo_config = find_monorepo_config(&self.config_files)\n            .ok_or_else(|| eyre!(\"no config file in scope sets monorepo_root = true\"))?;\n        let monorepo_root = monorepo_config\n            .project_root()\n            .ok_or_else(|| eyre!(\"monorepo root config has no project root\"))?;\n        let patterns = &monorepo_config\n            .monorepo()\n            .ok_or_else(|| eyre!(\"[monorepo].config_roots is required for monorepo operations\"))?\n            .config_roots;\n        if patterns.is_empty() {\n            bail!(\"[monorepo].config_roots is required for monorepo operations\");\n        }\n        let roots = match filenames {\n            Some(filenames) => {\n                expand_config_roots_with_filenames(&monorepo_root, patterns, None, filenames)?\n            }\n            None => expand_config_root_dirs(&monorepo_root, patterns, None)?,\n        };\n        if roots.is_empty() {\n            bail!(\"[monorepo].config_roots did not match any config roots\");\n        }\n        Ok(roots)\n    }\n\n    pub(crate) async fn monorepo_union_tool_request_set(\n        self: &Arc<Self>,\n    ) -> Result<ToolRequestSet> {\n        Ok(self.monorepo_union().await?.tool_request_set)\n    }","sourceCodeStart":765,"sourceCodeEnd":801,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/config/mod.rs#L765-L801","documentation":"Monorepo operations (expanding config roots, building the union toolset) require the config file that declares `monorepo_root = true` to also define a non-empty `[monorepo].config_roots` glob list. This error fires when that table is missing entirely or its config_roots array is empty.","triggerScenarios":"A mise.toml contains `monorepo_root = true` but no `[monorepo]` section, or `[monorepo]` with `config_roots = []`, and any command that needs the monorepo project graph or config roots runs (monorepo task loading, monorepo union).","commonSituations":"Copy-pasting a monorepo example that only sets monorepo_root; naming the table differently (e.g. `[workspace]`) so mise ignores it; assuming mise auto-detects subprojects without patterns.","solutions":["Add a `[monorepo]` table with non-empty globs relative to the monorepo root: `config_roots = [\"apps/*\", \"packages/*\"]`","Check the key location: config_roots belongs inside `[monorepo]`, not as a top-level key","If monorepo behavior was unintended, remove `monorepo_root = true` from the config"],"exampleFix":"# before\nmonorepo_root = true\n\n[tools]\nnode = \"22\"\n\n# after\nmonorepo_root = true\n\n[monorepo]\nconfig_roots = [\"apps/*\", \"packages/*\"]\n\n[tools]\nnode = \"22\"","handlingStrategy":"validation","validationCode":"grep -q 'monorepo_root = true' mise.toml && \\\n  awk '/^\\[monorepo\\]/{f=1} f && /^config_roots/{if ($0 ~ /\\[\\s*\\]/) exit 1; found=1} END{exit found?0:1}' mise.toml \\\n  && echo 'config_roots present' || echo 'missing/empty [monorepo].config_roots'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Whenever you set monorepo_root = true, add the [monorepo] config_roots globs in the same commit","config_roots lives inside the [monorepo] table, not at the top level","Write globs relative to the monorepo root config's directory","Cover this in a config smoke test: run a trivial mise command in CI to fail fast"],"tags":["mise","monorepo","config","missing-key"],"backgroundTag":"missing-required-setting","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}