{"record":{"id":"cb04c16a90ed79ed","repo":"openai/codex","slug":"invalid-patch-0","errorCode":null,"errorMessage":"invalid patch: {0}","messagePattern":"invalid patch: (.+?)","errorType":"exception","errorClass":"ParseError","httpStatus":null,"severity":"error","filePath":"codex-rs/apply-patch/src/parser.rs","lineNumber":57,"sourceCode":"pub(crate) const ADD_FILE_MARKER: &str = \"*** Add File: \";\npub(crate) const DELETE_FILE_MARKER: &str = \"*** Delete File: \";\npub(crate) const UPDATE_FILE_MARKER: &str = \"*** Update File: \";\npub(crate) const MOVE_TO_MARKER: &str = \"*** Move to: \";\npub(crate) const EOF_MARKER: &str = \"*** End of File\";\npub(crate) const CHANGE_CONTEXT_MARKER: &str = \"@@ \";\npub(crate) const EMPTY_CHANGE_CONTEXT_MARKER: &str = \"@@\";\n\n/// Currently, the only OpenAI model that knowingly requires lenient parsing is\n/// gpt-4.1. While we could try to require everyone to pass in a strictness\n/// param when invoking apply_patch, it is a pain to thread it through all of\n/// the call sites, so we resign ourselves allowing lenient parsing for all\n/// models. See [`ParseMode::Lenient`] for details on the exceptions we make for\n/// gpt-4.1.\nconst PARSE_IN_STRICT_MODE: bool = false;\n\n#[derive(Debug, PartialEq, Error, Clone)]\npub enum ParseError {\n    #[error(\"invalid patch: {0}\")]\n    InvalidPatchError(String),\n    #[error(\"invalid hunk at line {line_number}, {message}\")]\n    InvalidHunkError { message: String, line_number: usize },\n}\nuse ParseError::*;\n\n#[derive(Debug, PartialEq, Clone)]\n#[allow(clippy::enum_variant_names)]\npub enum Hunk {\n    AddFile {\n        path: PathBuf,\n        contents: String,\n    },\n    DeleteFile {\n        path: PathBuf,\n    },\n    UpdateFile {\n        path: PathBuf,","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/apply-patch/src/parser.rs#L39-L75","documentation":"Raised by the apply-patch parser when the patch text does not conform to the grammar at the whole-patch level (start: begin_patch hunk+ end_patch). The {0} string carries the specific reason - typically a missing '*** Begin Patch' header or '*** End Patch' trailer. The parser runs lenient by default (PARSE_IN_STRICT_MODE = false, kept lenient for gpt-4.1 quirks), so this fires only on fundamentally broken input, not minor whitespace deviations; hunk-level problems use InvalidHunkError instead.","triggerScenarios":"Passing text without the '*** Begin Patch'/'*** End Patch' markers to apply_patch; model output wrapped in markdown fences or prose; a response truncated before the end marker; hand-built patch strings missing the markers.","commonSituations":"LLM output that surrounds the patch with ``` fences or explanations; streaming responses cut mid-patch; encoding corruption of the first/last lines.","solutions":["Ensure the patch starts with '*** Begin Patch' and ends with '*** End Patch' on their own lines","Strip surrounding markdown fences and prose before handing model output to apply_patch","Check for truncation and regenerate the full patch","Read the {0} detail - it names the exact structural problem"],"exampleFix":"// before\nlet patch = raw_model_output; // wrapped in ``` fences -> InvalidPatchError\n\n// after\nlet patch = raw_model_output.trim()\n    .trim_start_matches('`').trim_start_matches(\"diff\").trim()\n    .trim_end_matches('`').trim();\ndebug_assert!(patch.starts_with(\"*** Begin Patch\") && patch.ends_with(\"*** End Patch\"));","handlingStrategy":"validation","validationCode":"fn looks_like_patch(s: &str) -> bool {\n    s.starts_with(\"*** Begin Patch\") && s.trim_end().ends_with(\"*** End Patch\")\n}\n\nif !looks_like_patch(&model_output) {\n    return Err(\"model did not emit a bare patch\");\n}","typeGuard":"fn is_invalid_patch(e: &ParseError) -> bool {\n    matches!(e, ParseError::InvalidPatchError(_))\n}","tryCatchPattern":"match apply_patch(patch, ...).await {\n    Err(failure) => match failure.into_parts().0 {\n        ApplyPatchError::ParseError(ParseError::InvalidPatchError(msg)) => {\n            eprintln!(\"patch malformed: {msg}\"); // log raw patch alongside\n        }\n        other => return Err(other.into()),\n    },\n    Ok(_) => {}\n}","preventionTips":["Strip markdown fences and prose from model output before applying","Assert both markers are present before calling apply_patch","Detect truncation (missing end marker) and re-request the full patch instead of parsing the fragment"],"tags":["rust","apply-patch","parser","validation"],"backgroundTag":"invalid-patch-format","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}