jdx/mise · error

new config Arc is uniquely owned

Error message

new config Arc is uniquely owned

What it means

mise panics with 'new config Arc is uniquely owned' when `Arc::get_mut(&mut config)` returns `None` in `with_bootstrap_dry_run_config_files`. The function builds a fresh config `Arc` via `from_dir`-style re-parse and then mutates it in place (`vars`, `tera_ctx`, bootstrap config maps). This is only legal while the new Arc has refcount 1; if anything else cloned the Arc, the mutation is impossible and the invariant is broken.

Source

Thrown at src/config/mod.rs:486

    ) -> Result<Arc<Self>> {
        let mut config = self.with_config_files(config_files);
        let bootstrap_roots = self
            .bootstrap_config_maps
            .iter()
            .filter_map(|map| map.config_root.as_deref())
            .collect_vec();
        let mut main_config_files = config.config_files.clone();
        main_config_files
            .retain(|path, _| !bootstrap_roots.iter().any(|root| path.starts_with(root)));
        let vars = bootstrap_dry_run_vars(
            Some(&self.config_files),
            self.vars_results_cached(),
            &main_config_files,
            IndexMap::new(),
            false,
        )?;
        let main_vars_changed = vars != self.vars;
        let config_mut = Arc::get_mut(&mut config).expect("new config Arc is uniquely owned");
        config_mut.vars = vars.clone();
        config_mut.tera_ctx.insert("vars", &vars);
        for map in &mut config_mut.bootstrap_config_maps {
            let original_config_files = map.config_files.clone();
            for (path, simulated) in &config_mut.config_files {
                let belongs_to_map = match &map.config_root {
                    Some(root) => path.starts_with(root),
                    None => !bootstrap_roots.iter().any(|root| path.starts_with(root)),
                };
                if belongs_to_map {
                    insert_bootstrap_dry_run_config_file(
                        &mut map.config_files,
                        path.clone(),
                        simulated.clone(),
                    );
                }
            }
            if map.config_root.is_some() {

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Ensure the config Arc returned by the parse step is not cloned or stored anywhere before `Arc::get_mut` runs
  2. If shared ownership is genuinely needed, wrap the mutated fields in `Arc::make_mut`/`RwLock` instead of relying on uniqueness
  3. Re-run the dry-run config build so a brand-new Arc is produced immediately before mutation
  4. Add a debug assertion or log near the parse call to catch accidental clones in development

Example fix

// before
let config = self.reparse_for_dry_run(&files)?;
let shared = config.clone(); // leaks a reference
let config_mut = Arc::get_mut(&mut config).expect("new config Arc is uniquely owned");
// after
let config = self.reparse_for_dry_run(&files)?;
// no clones before mutation
let config_mut = Arc::get_mut(&mut config).expect("new config Arc is uniquely owned");
Defensive patterns

Strategy: validation

Validate before calling

assert_eq!(Arc::strong_count(&config), 1, "config Arc must be uniquely owned before mutation");

Prevention

When it happens

Trigger: Calling `with_bootstrap_dry_run_config_files` when the freshly parsed config `Arc` was shared/cloned before reaching `Arc::get_mut` — e.g. a refactor stashes a clone of the new config (in a cache, guard, or closure) before the mutation block, or the config construction path returns an Arc that aliases an existing cached config.

Common situations: A developer introduces caching of the newly built config or holds a clone across the re-parse call; concurrent access to the config while the dry-run variant mutates it; changes to the config-load path that return a shared singleton instead of a fresh Arc.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/c3f0d35822e71087. Report an issue: GitHub.