rust-lang/cargo · error
already loaded config values
Error message
already loaded config values
What it means
This panic is in GlobalContext::values_mut(), which cargo vendor uses to mutate loaded config values. The method first calls self.values() (which lazy-loads config from disk via a OnceCell), then calls .get_mut() on that cell expecting it to now be filled. If the OnceCell's internal state is inconsistent — filled() reported true inside values() but get_mut() returns None — the expect fires.
Source
Thrown at src/context/mod.rs:657
/// Gets all config values from disk.
///
/// This will lazy-load the values as necessary. Callers are responsible
/// for checking environment variables. Callers outside of the `config`
/// module should avoid using this.
pub fn values(&self) -> CargoResult<&HashMap<String, ConfigValue>> {
self.values.try_borrow_with(|| self.load_values())
}
/// Gets a mutable copy of the on-disk config values.
///
/// This requires the config values to already have been loaded. This
/// currently only exists for `cargo vendor` to remove the `source`
/// entries. This doesn't respect environment variables. You should avoid
/// using this if possible.
pub fn values_mut(&mut self) -> CargoResult<&mut HashMap<String, ConfigValue>> {
let _ = self.values()?;
Ok(self.values.get_mut().expect("already loaded config values"))
}
// Note: this is used by RLS, not Cargo.
pub fn set_values(&self, values: HashMap<String, ConfigValue>) -> CargoResult<()> {
if self.values.get().is_some() {
bail!("config values already found")
}
match self.values.set(values.into()) {
Ok(()) => Ok(()),
Err(_) => bail!("could not fill values"),
}
}
/// Sets the path where ancestor config file searching will stop. The
/// given path is included, but its ancestors are not.
pub fn set_search_stop_path<P: Into<PathBuf>>(&mut self, path: P) {
let path = path.into();
debug_assert!(self.cwd.starts_with(&path));View on GitHub (pinned to 0e07a15537)
Solutions
- Call ctx.values() explicitly first to ensure config is loaded before calling values_mut().
- Check that config files are valid TOML and readable before attempting mutation.
- Avoid calling values_mut() from multiple threads — it requires &mut self so this should be impossible, but verify no unsafe aliasing exists in library embedding.
Defensive patterns
Strategy: validation
Validate before calling
// Ensure values are loaded before calling values_mut() let _ = ctx.values()?; // triggers lazy load // now safe to mutate let values = ctx.values_mut()?;
Prevention
- Always call ctx.values() before ctx.values_mut() to ensure the OnceCell is populated.
- Validate config files are readable and valid TOML before mutation operations.
- Avoid re-entrant config access patterns in library embedding.
When it happens
Trigger: Calling values_mut() without having previously called values() or load_values() successfully, or in a context where the OnceCell was reset/cleared between the borrow check and the get_mut call. In practice this path is only exercised by cargo vendor when stripping [source] entries.
Common situations: Running cargo vendor with a manually corrupted or partially-written config file; using cargo as a library and calling values_mut() after set_values() failed; a re-entrant config access pattern that resets the cell.
Related errors
- len() == 1 above
- must be utf-8 in toml
- local path
- venedored manifests must have packages
- previously normalized
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/0e23def644f66ad2.json.
Report an issue: GitHub.