openai/codex · error · ExecutorPluginConnectorProviderError
failed to read app config for selected plugin `{plugin_id}`
Error message
failed to read app config for selected plugin `{plugin_id}` at `{path}`: {source} What it means
ExecutorPluginConnectorProvider::load reads the apps/connector config file declared by a plugin manifest (paths.apps Environment locator) through the plugin's executor file system. ReadConfig wraps the io::Error from that read (NotFound, permission denied, sandbox denial, or executor transport failure). The message names the plugin id and the exact path that failed.
Source
Thrown at codex-rs/ext/connectors/src/executor_plugin.rs:17
use codex_connectors::parse_plugin_app_config;
use codex_core_plugins::ResolvedExecutorPlugin;
use codex_file_system::ReadFileOptions;
use codex_plugin::AppDeclaration;
use codex_plugin::PluginResourceLocator;
use codex_utils_path_uri::PathUri;
use std::io;
use thiserror::Error;
/// Loads connector declarations from a resolved plugin through its owning executor.
#[derive(Clone, Copy, Debug, Default)]
pub struct ExecutorPluginConnectorProvider;
/// Failure to load connector declarations from an executor plugin.
#[derive(Debug, Error)]
pub enum ExecutorPluginConnectorProviderError {
#[error("failed to read app config for selected plugin `{plugin_id}` at `{path}`: {source}")]
ReadConfig {
plugin_id: String,
path: PathUri,
#[source]
source: io::Error,
},
#[error("failed to parse app config for selected plugin `{plugin_id}` at `{path}`: {source}")]
ParseConfig {
plugin_id: String,
path: PathUri,
#[source]
source: serde_json::Error,
},
}
impl ExecutorPluginConnectorProvider {
/// Returns the connector declarations contributed by `plugin`.
#[tracing::instrument(name = "connectors.executor_plugin.declarations.load", skip_all)]View on GitHub (pinned to 339751715c)
Solutions
- Verify the file printed in the error exists at that path inside the plugin environment (it is the manifest's paths.apps value).
- Fix file permissions or sandbox rules so the executor can read it.
- Correct the paths.apps entry in the plugin manifest to match the installed layout.
- Reinstall or upgrade the plugin so manifest and files agree.
- If the plugin's connectors are optional, degrade to an empty declaration list instead of failing startup.
Defensive patterns
Strategy: try-catch
Try / catch
match provider.load(&plugin).await {
Ok(declarations) => declarations,
Err(ExecutorPluginConnectorProviderError::ReadConfig { plugin_id, path, source }) => {
tracing::warn!(%plugin_id, %path, %source, "plugin connectors unavailable");
Vec::new()
}
Err(e) => return Err(e.into()),
} Prevention
- Verify manifest paths.apps points at a shipped file during plugin packaging CI.
- Treat per-plugin connector load failures as skippable rather than fatal at host startup.
- Log plugin_id and path from the variant fields before dropping the error.
When it happens
Trigger: Calling ExecutorPluginConnectorProvider::load(&ResolvedExecutorPlugin) when the manifest points paths.apps at a file missing from the plugin environment, a file the executor cannot read, or when the executor file system cannot reach the environment.
Common situations: Plugin partially installed or its apps config deleted after registration; typo or stale path in the manifest's paths.apps; executor sandbox denies the read; plugin package reorganized its config layout between versions.
Related errors
- failed to read MCP config for selected plugin `{plugin_id}`
- failed to parse app config for selected plugin `{plugin_id}`
- failed to resolve MCP config path `{relative_path}` below se
- failed to parse MCP config for selected plugin `{plugin_id}`
- I/O error while reading memories: {0}
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/419c4c0a7beb7491.
Report an issue: GitHub.