openai/codex · error · io::Error

Managed config file {} has no parent directory

Error message

Managed config file {} has no parent directory

What it means

append_legacy_config_layers (codex-rs/config/src/loader/local.rs:231) folds the legacy managed-config file into the layer stack and needs its parent directory as the layer base_dir. If the managed config file path has no parent (a filesystem root or empty path), it returns ErrorKind::InvalidData. It is reached via load_local_config_layers_with_overrides whenever a legacy managed config was found.

Source

Thrown at codex-rs/config/src/loader/local.rs:238

            },
            base_dir: hooks_config_folder,
            toml: TomlValue::Table(toml::map::Map::from_iter([(
                "hooks".to_string(),
                hooks.clone(),
            )])),
        });
    }
    Ok(())
}

fn append_legacy_config_layers(
    output: &mut Vec<LocalTomlLayer<ConfigLayerSource>>,
    loaded: layer_io::LoadedConfigLayers,
    codex_home: &AbsolutePathBuf,
) -> io::Result<()> {
    if let Some(config) = loaded.managed_config {
        let base_dir = config.file.parent().ok_or_else(|| {
            io::Error::new(
                io::ErrorKind::InvalidData,
                format!(
                    "Managed config file {} has no parent directory",
                    config.file.as_path().display()
                ),
            )
        })?;
        output.push(LocalTomlLayer {
            source: ConfigLayerSource::LegacyManagedConfigTomlFromFile { file: config.file },
            base_dir,
            toml: config.managed_config,
        });
    }
    if let Some(config) = loaded.managed_config_from_mdm {
        output.push(LocalTomlLayer {
            source: ConfigLayerSource::LegacyManagedConfigTomlFromMdm,
            base_dir: codex_home.clone(),
            toml: config.managed_config,

View on GitHub (pinned to 339751715c)

Solutions

  1. Set the managed config location to a real file path inside a directory
  2. Verify where the managed config path comes from (default system path versus override) and correct the deployment
  3. Remove the stray managed-config entry so the loader skips the legacy layer entirely
Defensive patterns

Strategy: validation

Validate before calling

if let Some(managed) = &loaded.managed_config {
    anyhow::ensure!(
        managed.file.as_path().parent().is_some(),
        "managed config path has no parent: {}",
        managed.file.display()
    );
}

Type guard

fn has_parent_dir(p: &std::path::Path) -> bool {
    p.parent().is_some()
}

Try / catch

match load_local_config_layers_with_overrides(...).await {
    Err(e) if e.kind() == io::ErrorKind::InvalidData
        && e.to_string().contains("Managed config file") =>
    {
        // correct the managed-config deployment path, then reload
    }
    r => r?,
}

Prevention

When it happens

Trigger: loaded.managed_config is Some but config.file is a filesystem root or empty string: an MDM/managed-config location override or deployment wrote the wrong path for the legacy managed config file.

Common situations: Enterprise deployment scripts or MDM profiles misconfigure the managed config location; container images symlinking the managed config path at a root; testing with hand-set managed config paths.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/78528b0f3adcf27d. Report an issue: GitHub.