clockworklabs/SpacetimeDB · error

Environment key is both supplied and removed

Error message

Environment key {key:?} is both supplied and removed

What it means

`validate_values` iterates the `--unset-env` keys and rejects any key that also appears in the supplied values map (from `--env KEY=VALUE` or shell lookups). Supplying and removing the same key in one publication is ambiguous — the CLI refuses to guess which wins.

Solutions

  1. Remove the key from one of the two lists — keep `--env KEY=value` if you want the new value, or `--unset-env KEY` if you want it gone.
  2. Audit the resolved values map (including shell-derived values) before publishing to check for overlap with `remove`.
  3. If you intended to change a key, just supply `--env KEY=newvalue` without unsetting it.

Example fix

// before
spacetime publish --env FOO=bar --unset-env FOO -d mydb
// after
spacetime publish --env FOO=newbar -d mydb
Defensive patterns

Strategy: validation

Validate before calling

// rust: caller-side pre-check mirroring the CLI rule
let overlap: Vec<_> = options.remove.iter().filter(|k| values.contains_key(*k)).collect();
if !overlap.is_empty() {
    panic!("keys both supplied and unset: {overlap:?}");
}

Prevention

When it happens

Trigger: `spacetime publish --env FOO=bar --unset-env FOO`; supplying FOO via shell environment while also listing FOO in `--unset-env`; programmatic EnvironmentOptions where `values` contains a key present in `remove`.

Common situations: Scripts built from lists of keys where a key accidentally appears in both an override list and a removal list; stale flag files where a key was previously removed but a new `--env` line was added for it.

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 clockworklabs/SpacetimeDB@eddf9f5014 (2026-09-20). Data as JSON: /api/errors/705bb2220548152e. Report an issue: GitHub.

Appendix: source

Thrown at crates/cli/src/subcommands/publish.rs:388

            replace: args.get_flag("replace_env"),
        };
        ensure!(
            options.remove.len() <= spacetimedb_lib::environment::MAX_ENV_VARS,
            "Too many environment removals"
        );
        for key in &options.remove {
            spacetimedb_lib::environment::validate_key(key)?;
        }
        Ok(options)
    }

    fn validate_values(&self, values: &std::collections::BTreeMap<String, String>) -> anyhow::Result<()> {
        ensure!(
            !self.replace || self.remove.is_empty(),
            "--replace-env cannot be combined with --unset-env"
        );
        for key in &self.remove {
            ensure!(
                !values.contains_key(key),
                "Environment key {key:?} is both supplied and removed"
            );
        }
        Ok(())
    }
}

fn publication_body(
    module: &spacetimedb_schema::def::ModuleDef,
    bytes: Vec<u8>,
    environment: std::collections::BTreeMap<String, String>,
    options: &EnvironmentOptions,
) -> anyhow::Result<(&'static str, Vec<u8>)> {
    options.validate_values(&environment)?;
    if module.environment_declared() || !environment.is_empty() || !options.remove.is_empty() || options.replace {
        let body = spacetimedb_client_api_messages::publish::PublishRequest {
            module: Some(bytes),

View on GitHub (pinned to eddf9f5014)