clockworklabs/SpacetimeDB · error

Invalid environment key name

Error message

Invalid environment key name

What it means

The `spacetime env get` subcommand builds a SQL query embedding the key into a WHERE clause. Before doing so it runs validate_key, which enforces POSIX-style names (no quotes or SQL metacharacters); a failing key aborts with this error to prevent SQL injection into the st_env query.

Solutions

  1. Re-run with a bare POSIX-style key: letters, digits, underscores (e.g. MY_API_KEY), no quotes.
  2. Use `spacetime env list` to see the exact valid key names, then copy one verbatim.
  3. Remove shell-added quotes: pass the key unquoted/unescaped in the command.
  4. Fix upstream tooling that writes non-conforming keys into st_env.

Example fix

// before
spacetime env get "MY_KEY"
// after
spacetime env get MY_KEY
Defensive patterns

Strategy: validation

Validate before calling

const keyOk = /^[A-Za-z_][A-Za-z0-9_]*$/.test(key); if (!keyOk) throw new Error(`Key must be POSIX-style (letters, digits, underscore): ${key}`);

Try / catch

// shell: validate before invoking
[[ "$KEY" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]] || { echo "invalid key" >&2; exit 1; }

Prevention

When it happens

Trigger: Running `spacetime env get <key>` where <key> contains quotes, spaces, semicolons, or other characters disallowed by validate_key — or is empty.

Common situations: Copy-pasting keys with surrounding quotes from documentation or JSON, keys containing dashes/paths set via other tooling, or shell quoting mistakes injecting extra characters.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@eddf9f5014 (2026-09-20). Data as JSON: /api/errors/62f1e89bfaf73b01. Report an issue: GitHub.

Appendix: source

Thrown at crates/cli/src/subcommands/env.rs:59

            ),
        ))
        .subcommand(target(
            Command::new("list").about("List published environment keys and values"),
        ))
}

#[derive(Clone)]
enum Query {
    List,
    Get(String),
}
impl Query {
    fn sql(&self) -> anyhow::Result<String> {
        match self {
            Self::List => Ok("SELECT key, value FROM st_env".into()),
            Self::Get(key) => {
                // POSIX names cannot contain quotes or SQL syntax.
                validate_key(key).map_err(|_| anyhow::anyhow!("Invalid environment key name"))?;
                Ok(format!("SELECT value FROM st_env WHERE key = '{key}'"))
            }
        }
    }
}

pub async fn exec(config: Config, args: &ArgMatches) -> anyhow::Result<()> {
    let (command, args) = args.subcommand().context("Expected env get or list")?;
    let query = match command {
        "list" => Query::List,
        "get" => Query::Get(
            args.get_one::<String>("key")
                .context("Expected environment key")?
                .clone(),
        ),
        _ => anyhow::bail!("Environment values can only be changed by publishing"),
    };
    query.sql()?;

View on GitHub (pinned to eddf9f5014)