openai/codex · error · StartupOutcomeError

non-local HTTP MCP server `{server_name}` did not resolve an

Error message

non-local HTTP MCP server `{server_name}` did not resolve an execution environment

What it means

For a non-local streamable-http server with bearer_token_env_var, Codex must ask the resolved execution environment whether the executor resolves that token (its http_header_env_vars capability). resolved_environment came back Ok(None) - no environment attached - so the decision cannot be made and the server refuses to start rather than silently reading the token from the wrong (local) environment.

Source

Thrown at codex-rs/codex-mcp/src/rmcp_client.rs:1152

            .await
            .map_err(|err| StartupOutcomeError::from(anyhow!(err)))
        }
        McpServerTransportConfig::StreamableHttp {
            url,
            http_headers,
            env_http_headers,
            bearer_token_env_var,
            http_headers_helper: _,
        } => {
            let http_client = runtime_context
                .http_client_for_server(server.config(), resolved_environment.as_ref())
                .map_err(|error| StartupOutcomeError::from(anyhow!(error)))?;
            let http_client = maybe_with_openai_docs_source_attribution(&url, http_client);
            let executor_resolves_bearer_token = if !is_local_environment
                && bearer_token_env_var.is_some()
            {
                let Some(environment) = resolved_environment.as_ref() else {
                    return Err(StartupOutcomeError::from(anyhow!(
                        "non-local HTTP MCP server `{server_name}` did not resolve an execution environment"
                    )));
                };
                environment
                    .info()
                    .await
                    .map_err(|error| StartupOutcomeError::from(anyhow!(error)))?
                    .capabilities
                    .http_header_env_vars
            } else {
                false
            };
            let (http_client, resolved_bearer_token) = if executor_resolves_bearer_token
                && let Some(env_var) = bearer_token_env_var.as_ref()
            {
                (
                    Arc::new(ExecutorEnvironmentHttpClient {
                        bearer_token_env_var: env_var.clone(),

View on GitHub (pinned to 339751715c)

Solutions

  1. Fix or restore the execution-environment reference so resolution returns an environment (register/repair it in the exec-server the runtime talks to)
  2. Align app-server and exec-server versions so environment resolution agrees
  3. If the server actually runs locally, remove the non-local environment setting so the token resolves from the host env
Defensive patterns

Strategy: validation

Validate before calling

// Only start non-local HTTP servers with bearer tokens once an environment resolved
if !cfg.is_local_environment()
    && cfg.bearer_token_env_var.is_some()
    && resolved_environment.as_ref().map_or(true, |e| e.is_none())
{
    return Err(anyhow::anyhow!("no execution environment for {}", server_name));
}

Prevention

When it happens

Trigger: Config marks an HTTP MCP server as non-local and sets bearer_token_env_var, but environment resolution produced None: the referenced execution environment is missing or unregistered, was removed between config publish and server start, or app-server and exec-server versions disagree on environment resolution.

Common situations: Cloud executor misconfiguration with a dangling environment reference; exec-server older than the app-server; race where a config referencing an environment is applied before the environment is registered.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/f3e23d4032b23bd6. Report an issue: GitHub.