aaif-goose/goose · error · anyhow::Error

GOOSE_SERVER__SECRET_KEY must be set to start `goose serve`;

Error message

GOOSE_SERVER__SECRET_KEY must be set to start `goose serve`; pass --dangerously-unauthenticated to run without ACP authentication

What it means

anyhow bail from the 'goose serve' startup (crates/goose-cli/src/cli.rs). The ACP server requires authentication by default: it reads GOOSE_SERVER__SECRET_KEY from the environment, trims it, and treats empty as unset. If the key is absent/empty and --dangerously-unauthenticated was not passed, startup refuses with this message.

Source

Thrown at crates/goose-cli/src/cli.rs:1452

            SourceRoot::read_only(path)
        })
        .collect();

    let server = Arc::new(AcpServer::new(AcpServerFactoryConfig {
        builtins,
        data_dir: Paths::data_dir(),
        config_dir: Paths::config_dir(),
        goose_platform: platform.into(),
        additional_source_roots,
        enable_scheduler,
    }));
    let env_secret = std::env::var(GOOSE_SERVER_SECRET_KEY_ENV)
        .ok()
        .map(|secret| secret.trim().to_string())
        .filter(|secret| !secret.is_empty());
    let require_token = env_secret.is_some();
    if !require_token && !dangerously_unauthenticated {
        anyhow::bail!(
            "{GOOSE_SERVER_SECRET_KEY_ENV} must be set to start `goose serve`; pass --dangerously-unauthenticated to run without ACP authentication"
        );
    }
    if dangerously_unauthenticated && !require_token {
        warn!(
            "{GOOSE_SERVER_SECRET_KEY_ENV} is not set and --dangerously-unauthenticated was passed; the ACP endpoint will accept unauthenticated connections"
        );
    }
    let additional_allowed_origins = allowed_origins
        .into_iter()
        .map(|origin| {
            let origin = origin.trim();
            if origin.is_empty() || origin == "*" {
                anyhow::bail!("--allowed-origin must be a non-wildcard Origin value");
            }
            HeaderValue::from_str(origin).map_err(|error| {
                anyhow::anyhow!("invalid --allowed-origin value `{origin}`: {error}")
            })

View on GitHub (pinned to 3810898a74)

Solutions

  1. Set the env var to a strong random value: export GOOSE_SERVER__SECRET_KEY="$(openssl rand -hex 32)"
  2. Double-check the exact name — it uses double underscores: GOOSE_SERVER__SECRET_KEY
  3. Ensure the value is non-empty after trimming (no quotes-only or whitespace-only exports)
  4. For local, trusted experimentation only: goose serve --dangerously-unauthenticated (it warns and accepts unauthenticated connections)

Example fix

# before
goose serve

# after
export GOOSE_SERVER__SECRET_KEY="$(openssl rand -hex 32)"
goose serve
Defensive patterns

Strategy: validation

Validate before calling

import os
key = os.environ.get("GOOSE_SERVER__SECRET_KEY", "").strip()
if not key:
    raise SystemExit("set GOOSE_SERVER__SECRET_KEY (note double underscore) before `goose serve`")

Prevention

When it happens

Trigger: Running 'goose serve' (or the desktop platform variant) with GOOSE_SERVER__SECRET_KEY unset, set to an empty string, or containing only whitespace, without passing --dangerously-unauthenticated.

Common situations: First-time serve usage; CI/container where the env var was not injected; double-underscore typo (GOOSE_SERVER_SECRET_KEY instead of GOOSE_SERVER__SECRET_KEY); a .env file not loaded into the actual environment.

Understand the failure class

Related errors


AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16). Data as JSON: /api/errors/989fc8656739352a. Report an issue: GitHub.