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
- Set the env var to a strong random value: export GOOSE_SERVER__SECRET_KEY="$(openssl rand -hex 32)"
- Double-check the exact name — it uses double underscores: GOOSE_SERVER__SECRET_KEY
- Ensure the value is non-empty after trimming (no quotes-only or whitespace-only exports)
- 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
- Export a generated secret in the serve environment: GOOSE_SERVER__SECRET_KEY=$(openssl rand -hex 32)
- Note the double underscores in the variable name
- Inject it via secret manager/env file in containers — never commit it
- Use --dangerously-unauthenticated only on an isolated loopback machine
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
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- --allowed-origin must be a non-wildcard Origin value
- invalid --allowed-origin value `{origin}`: {error}
- GOOSE_BINARY is only supported in development builds
- Invalid GOOSE_BINARY path: ${pathFromEnv} (pwd is ${process.
- GOOSE_SERVER__SECRET_KEY must be set when using GOOSE_EXTERN
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/989fc8656739352a.
Report an issue: GitHub.