Hmbown/CodeWhale · error

bundle carries [global] entries; importing them into a…

Error message

bundle carries [global] entries; importing them into a project document would leak machine state

What it means

prepare_import refuses to import a bundle whose Project scope carries [global] entries. Importing machine-specific global configuration (providers, credentials, store paths) into a workspace-scoped project document would leak state from one machine into a shared/committed file. The library throws this as a guard before any plan is built or written.

Solutions

  1. Import without --project so the [global] entries land in the global document, as the message suggests.
  2. Edit the bundle file to remove the [global] section (or split it into a separate global bundle) before importing with --project.
  3. Re-export with `config export --portable --project` so only project-scoped entries are in the bundle.

Example fix

// before
codewhale config import team-bundle.toml --project
// after (global entries handled separately)
codewhale config import global-part.toml
codewhale config import project-part.toml --project
Defensive patterns

Strategy: validation

Validate before calling

let text = std::fs::read_to_string(&bundle_path)?;
let bundle: toml::Table = toml::from_str(&text)?;
let has_global = bundle.get("global").map(|t| t.as_table().map(|t| !t.is_empty()).unwrap_or(false)).unwrap_or(false);
if has_global && args.project { eprintln!("bundle has [global] entries; drop --project or split the bundle"); }

Type guard

fn importable_as_project(bundle: &Bundle) -> bool { bundle.global.entries.is_empty() }

Try / catch

match prepare_import(&bundle, &store, BundleScope::Project) {
    Err(e) if e.to_string().contains("leak machine state") => eprintln!("re-run without --project"),
    other => other?,
}

Prevention

When it happens

Trigger: Calling apply_bundle/run_import (or the dry-run path via prepare_import) with scope=BundleScope::Project while bundle.global.entries is non-empty; typically the bundle was exported as Global or contains both sections and the user passed --project.

Common situations: Sharing a bundle exported on a personal machine into a team repo; exporting with mixed sections and importing with --project; scripting `config import --project` against a bundle fetched from a remote source that includes [global] entries.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/1c5e55ec04da9228. Report an issue: GitHub.

Appendix: source

Thrown at crates/cli/src/config_bundles.rs:1149

        Ok(()) => Ok(()),
        Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(()),
        Err(error) => Err(error)
            .with_context(|| format!("removing newly-created config {}", target.display())),
    }
}

/// Build the exact candidate used for both preview and commit. Legacy route
/// migration remains in memory until the existing ConfigStore CAS save.
fn prepare_import(
    bundle: &PortableBundle,
    store: &codewhale_config::ConfigStore,
    scope: BundleScope,
) -> Result<PreparedImport> {
    match scope {
        BundleScope::Global if !bundle.project.entries.is_empty() => bail!(
            "bundle carries [project] entries; import it with --project from the workspace instead"
        ),
        BundleScope::Project if !bundle.global.entries.is_empty() => bail!(
            "bundle carries [global] entries; importing them into a project document would leak machine state"
        ),
        _ => {}
    }
    validate_scope_target(scope, store.path())?;
    let mut plan = plan_import(bundle, &store.config, scope);
    if !plan.conflicting.is_empty() || (plan.is_no_op() && plan.skipped.is_empty()) {
        return Ok(PreparedImport {
            plan,
            candidate: store.config.clone(),
        });
    }
    let rendered;
    let original = if let Some(original) = store.original_body() {
        original
    } else {
        rendered = store.rendered_body()?;
        &rendered

View on GitHub (pinned to 73e0f67d83)