{"record":{"id":"aa4694dc8b03848a","repo":"openai/codex","slug":"agent-graph-store-internal-error-message","errorCode":null,"errorMessage":"agent graph store internal error: {message}","messagePattern":"agent graph store internal error: (.+?)","errorType":"error_code","errorClass":"AgentGraphStoreError","httpStatus":null,"severity":"error","filePath":"codex-rs/agent-graph-store/src/error.rs","lineNumber":15,"sourceCode":"/// Result type returned by agent graph store operations.\npub type AgentGraphStoreResult<T> = Result<T, AgentGraphStoreError>;\n\n/// Error type shared by agent graph store implementations.\n#[derive(Debug, thiserror::Error)]\npub enum AgentGraphStoreError {\n    /// The caller supplied invalid request data.\n    #[error(\"invalid agent graph store request: {message}\")]\n    InvalidRequest {\n        /// User-facing explanation of the invalid request.\n        message: String,\n    },\n\n    /// Catch-all for implementation failures that do not fit a more specific category.\n    #[error(\"agent graph store internal error: {message}\")]\n    Internal {\n        /// User-facing explanation of the implementation failure.\n        message: String,\n    },\n}\n","sourceCodeStart":1,"sourceCodeEnd":21,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/agent-graph-store/src/error.rs#L1-L21","documentation":"Each inject_request_headers entry must declare exactly one secret source. The match on (secret_env_var, secret_file) accepts (Some, None) and (None, Some); the wildcard arm rejects both (Some, Some) and (None, None). Both fields are Options defaulting to None via serde, so the most common cause is simply omitting both fields from the header entry.","triggerScenarios":"inject_request_headers = [{ name = \"authorization\", prefix = \"Bearer \" }] with neither secret field set, or an entry that sets both secret_env_var and secret_file at once — for example while switching from env-var to file-based secrets without deleting the old key.","commonSituations":"Forgetting the secret source entirely when adding a hook; setting both during a migration; config merging tools that concatenate fields from two variants of an entry.","solutions":["Set exactly one of secret_env_var or secret_file on the entry","If switching sources, delete the other key rather than leaving both","Prefer secret_env_var for CI/deployments where secrets come from the environment, secret_file for machine-local secrets"],"exampleFix":"// config.toml — before\n[[network.mitm_hooks.actions.inject_request_headers]]\nname = \"authorization\"\nprefix = \"Bearer \"\n\n// after\n[[network.mitm_hooks.actions.inject_request_headers]]\nname = \"authorization\"\nsecret_env_var = \"CODEX_GITHUB_TOKEN\"\nprefix = \"Bearer \"","handlingStrategy":"validation","validationCode":"for header in &hook.actions.inject_request_headers {\n    match (header.secret_env_var.as_deref(), header.secret_file.as_deref()) {\n        (Some(_), None) | (None, Some(_)) => {}\n        _ => return Err(anyhow!(\"{} needs exactly one of secret_env_var or secret_file\", header.name)),\n    }\n}","typeGuard":"fn secret_source_unique(header: &InjectedHeaderConfig) -> bool {\n    matches!(\n        (header.secret_env_var.as_deref(), header.secret_file.as_deref()),\n        (Some(_), None) | (None, Some(_))\n    )\n}","tryCatchPattern":null,"preventionTips":["serde defaults make both-None silent — lint injected-header entries for a missing source","When switching secret sources, delete the old key in the same change","Encode the choice as a single tagged field in upstream config generators"],"tags":["rust","network-proxy","mitm-hooks","secrets","config-validation"],"backgroundTag":"config-validation-failed","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}