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

  1. Verify the file printed in the error exists at that path inside the plugin environment (it is the manifest's paths.apps value).
  2. Fix file permissions or sandbox rules so the executor can read it.
  3. Correct the paths.apps entry in the plugin manifest to match the installed layout.
  4. Reinstall or upgrade the plugin so manifest and files agree.
  5. 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

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


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