aaif-goose/goose · error · anyhow::Error
missing required key {}: {}
Error message
missing required key {}: {} What it means
The Ollama declarative config names an api key environment variable via api_key_env, and the key resolver (which reads that env var) failed while the config also sets requires_auth: true — so the missing key is fatal instead of being ignored. The message names both the env var and the underlying resolver error. If requires_auth were false (or unset), a failing resolve would just mean no auth header, which suits local Ollama servers that don't check keys.
Source
Thrown at crates/goose-providers/src/ollama.rs:323
let mut base_url = Url::parse(&base)
.map_err(|e| anyhow::anyhow!("Invalid base URL '{}': {}", config.base_url, e))?;
let is_localhost = matches!(base_url.host_str(), Some("localhost" | "127.0.0.1" | "::1"));
if base_url.port().is_none() && !base_has_scheme && is_localhost {
base_url
.set_port(Some(OLLAMA_DEFAULT_PORT))
.map_err(|_| anyhow::anyhow!("Failed to set default port"))?;
}
let api_key = if config.api_key_env.is_empty() {
None
} else {
match key_resolver.resolve_key(config.api_key_env.as_str()) {
Ok(key) => Some(key),
Err(err) => {
if config.requires_auth {
anyhow::bail!("missing required key {}: {}", config.api_key_env, err);
}
None
}
}
};
let auth = match api_key {
Some(key) if !key.is_empty() => AuthMethod::BearerToken(key),
_ => AuthMethod::NoAuth,
};
let mut api_client =
ApiClient::with_timeout_and_tls(base_url.to_string(), auth, timeout, tls_config)?;
if let Some(headers) = &config.headers {
let mut header_map = reqwest::header::HeaderMap::new();
for (key, value) in headers {
let header_name = reqwest::header::HeaderName::from_bytes(key.as_bytes())?;View on GitHub (pinned to 3810898a74)
Solutions
- Export the named variable in goose's environment: export OLLAMA_API_KEY=... (match the name in api_key_env exactly, case included)
- For a local Ollama with no auth in front, set "requires_auth": false so a missing key is tolerated
- If a proxy is optional, prefer requires_auth: false and supply the key only when present
- Double-check api_key_env spelling — a var that never exists will always fail when required
Example fix
// before
{ "name": "proxied-ollama", "engine": "ollama", "base_url": "https://llm.internal:11434",
"api_key_env": "OLLAMA_API_KEY", "requires_auth": true }
// OLLAMA_API_KEY not exported -> missing required key OLLAMA_API_KEY
// after
export OLLAMA_API_KEY=sk-... # or, for plain local servers:
// "requires_auth": false Defensive patterns
Strategy: validation
Validate before calling
fn ollama_auth_satisfiable(api_key_env: &str, requires_auth: bool) -> anyhow::Result<()> {
if requires_auth && !api_key_env.is_empty() && std::env::var(api_key_env).is_err() {
anyhow::bail!("export {api_key_env} (required by this provider) or set requires_auth=false");
}
Ok(())
} Try / catch
// Pre-flight all required key env vars once at startup and list them together:
let missing: Vec<_> = providers.iter()
.filter(|p| p.requires_auth && std::env::var(&p.api_key_env).is_err())
.map(|p| p.api_key_env.clone()).collect();
anyhow::ensure!(missing.is_empty(), "missing required API key env vars: {}", missing.join(", ")); Prevention
- Set requires_auth:true only for endpoints that actually verify a key; local Ollama doesn't
- Wire secrets through environment injection (dotenv, systemd, k8s) and verify with a pre-flight check
- Keep api_key_env names in provider JSON aligned with the names your secret store injects (case-sensitive)
When it happens
Trigger: A declarative Ollama provider JSON with "api_key_env": "OLLAMA_API_KEY" (any name) and "requires_auth": true, run where that environment variable is not set — e.g. routing through an auth-gating proxy (LiteLLM, corporate gateway) in CI that lacks the secret.
Common situations: Teams front Ollama with an authenticating proxy and forget the secret in CI/service environments; the env var name in JSON has a typo or case mismatch versus what's exported; local setups copied a remote team's config but don't run the proxy, so the var was never needed before.
Related errors
- Required environment variable {} is not set
- Provider '{}' has dynamic_models: false but no static models
- Invalid base URL '{}': {}
- Ollama provider does not support non-streaming mode. All Oll
- GOOSE_SERVER__SECRET_KEY must be set to start `goose serve`;
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/e6a7983ab5e1f497.
Report an issue: GitHub.