{"record":{"id":"2965363403264d0f","repo":"openai/codex","slug":"path-prefixes-must-not-contain-empty-entries","errorCode":null,"errorMessage":"path_prefixes must not contain empty entries","messagePattern":"path_prefixes must not contain empty entries","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"codex-rs/network-proxy/src/mitm_hook.rs","lineNumber":483,"sourceCode":"}\n\nimpl ValueMatcher {\n    fn matches(&self, candidate: &str) -> bool {\n        match self {\n            Self::Exact(value) => value == candidate,\n            Self::Glob(glob) => glob.is_match(candidate),\n        }\n    }\n}\n\nfn compile_path_matchers(path_prefixes: &[String]) -> Result<Vec<PathMatcher>> {\n    path_prefixes\n        .iter()\n        .map(|prefix| {\n            match parse_matcher_pattern(prefix)? {\n                MatcherPattern::Literal(prefix) => {\n                    if prefix.is_empty() {\n                        return Err(anyhow!(\"path_prefixes must not contain empty entries\"));\n                    }\n                    Ok(PathMatcher::Prefix(prefix.to_string()))\n                }\n                MatcherPattern::Glob(glob_pattern) => Ok(PathMatcher::Glob(compile_glob_matcher(\n                    glob_pattern,\n                    /*literal_separator*/ true,\n                )?)),\n            }\n        })\n        .collect()\n}\n\nfn compile_value_matchers(values: &[String]) -> Result<Vec<ValueMatcher>> {\n    values\n        .iter()\n        .map(|value| match parse_matcher_pattern(value)? {\n            MatcherPattern::Literal(value) => Ok(ValueMatcher::Exact(value.to_string())),\n            MatcherPattern::Glob(glob_pattern) => Ok(ValueMatcher::Glob(compile_glob_matcher(","sourceCodeStart":465,"sourceCodeEnd":501,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/network-proxy/src/mitm_hook.rs#L465-L501","documentation":"compile_path_matchers turns each path_prefixes entry into either a Prefix literal or a compiled glob. A literal entry that is empty after parsing — the empty string, or 'literal:' with nothing after the colon — is meaningless as a prefix and is rejected with 'path_prefixes must not contain empty entries'. An empty list is a different error ('must not be empty').","triggerScenarios":"path_prefixes = [\"\"], path_prefixes = [\"/v1/\", \"\"], or path_prefixes = [\"literal:\"] inside any [[network.mitm_hooks]] entry; note that 'pattern:' with an empty body raises the separate 'glob pattern must not be empty' error.","commonSituations":"Template loops or concatenation emitting an empty iteration; copying a path list with a blank line; intending 'match everything' and leaving a blank entry instead of \"/\".","solutions":["Delete empty strings from path_prefixes","To match every path use \"/\" — every request path starts with a slash","Use pattern: globs such as \"pattern:/api/*/items\" when plain prefix matching is too coarse"],"exampleFix":"# before\npath_prefixes = [\"/v1/\", \"\"]\n\n# after\npath_prefixes = [\"/v1/\"]","handlingStrategy":"validation","validationCode":"// Rust — no empty literal prefix entries\nfor hook in &config.mitm_hooks {\n    if hook.matcher.path_prefixes.iter()\n        .any(|p| p.is_empty() || p == \"literal:\")\n    {\n        return Err(anyhow!(\"path_prefixes contains an empty entry\"));\n    }\n}","typeGuard":"fn path_prefixes_are_nonempty(hook: &MitmHookConfig) -> bool {\n    hook.matcher.path_prefixes.iter().all(|p| !p.is_empty() && p != \"literal:\")\n}","tryCatchPattern":"match validate_mitm_hook_config(&config) {\n    Ok(()) => {}\n    Err(err) => eprintln!(\"{err:#}\"), // context names the hook and path_prefixes field\n}","preventionTips":["Use \"/\" when you mean match-all instead of a blank entry","Filter empty strings out of generated lists before writing config","Validate hook TOML with the crate's own validator before deploy"],"tags":["network","mitm","codex","config-validation","path-matching"],"backgroundTag":"config-validation-failed","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}