jdx/mise · error

config index exists

Error message

config index exists

What it means

mise panics with 'config index exists' in the bootstrap config sibling-insertion logic when `config_files.get_index(*index)` returns `None` for an index taken from `sibling_indices`. Those indices are recorded while iterating the same IndexMap, so they must remain valid; the panic means the map shrank or was rebuilt between recording the indices and using them for precedence-based insertion (`shift_insert` of a bootstrap config file).

Solutions

  1. Recompute sibling indices immediately before the precedence lookup instead of caching them across mutations
  2. Verify no code path removes entries from `config_files` between index collection and `shift_insert`
  3. Add a bounds check and skip stale indices rather than panicking
  4. Reproduce with the layered config set that triggers sibling dedup to identify which mutation drops the entry

Example fix

// before
.find(|index| config_files.get_index(*index).expect("config index exists").0)
// after
.find(|index| config_files.get_index(*index).map(|(k, _)| k).is_some_and(|k| bootstrap_config_filename_precedence(k) < precedence))
Defensive patterns

Strategy: validation

Validate before calling

if config_files.get_index(i).is_none() { continue; } // skip stale sibling index

Type guard

fn valid_index(map: &ConfigFiles, i: usize) -> bool { i < map.len() }

Prevention

When it happens

Trigger: Running the bootstrap config-file ordering code when `config_files` is mutated (entries removed/merged) between collecting `sibling_indices` and the precedence `find` that dereferences them — e.g. layered config loading removes a file, or the index list was computed against a different map instance.

Common situations: Bootstrap `[config]` declarations referencing sibling config files that get deduplicated or dropped during layered load; env-specific config filtering shrinking the map mid-pass; refactors that reorder collection of sibling indices.

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/e9b3baa36ef7bbe5. Report an issue: GitHub.

Appendix: source

Thrown at src/config/mod.rs:1668

        config_files.insert(path, config_file);
        return;
    }

    let precedence = bootstrap_config_filename_precedence(&path);
    let sibling_indices = config_files
        .keys()
        .enumerate()
        .filter(|(_, existing)| existing.parent() == path.parent())
        .map(|(index, _)| index)
        .collect_vec();
    let index = sibling_indices
        .iter()
        .copied()
        .find(|index| {
            bootstrap_config_filename_precedence(
                config_files
                    .get_index(*index)
                    .expect("config index exists")
                    .0,
            ) < precedence
        })
        .or_else(|| sibling_indices.last().map(|index| index + 1))
        .unwrap_or(config_files.len());
    config_files.shift_insert(index, path, config_file);
}

fn bootstrap_config_filename_precedence(path: &Path) -> Option<usize> {
    DEFAULT_CONFIG_FILENAMES.iter().position(|candidate| {
        !is_glob_pattern(candidate) && Path::new(candidate).file_name() == path.file_name()
    })
}

fn configs_at_root<'a>(dir: &Path, config_files: &'a ConfigMap) -> Vec<&'a Arc<dyn ConfigFile>> {
    // Highest precedence config files are returned first.
    let mut configs: Vec<&'a Arc<dyn ConfigFile>> = DEFAULT_CONFIG_FILENAMES
        .iter()

View on GitHub (pinned to afd2eddd3a)