{"record":{"id":"766941fb3073377c","repo":"theonedev/onedev","slug":"invalid-patch-mode-sign-in-line","errorCode":null,"errorMessage":"Invalid patch mode '${sign}' in: ${line}","messagePattern":"Invalid patch mode '(.+?)' in: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/util/diff/DiffMatchPatch.java","lineNumber":2363,"sourceCode":"\t\t\t\t\t// Malformed URI sequence.\n\t\t\t\t\tthrow new IllegalArgumentException(\"Illegal escape in patch_fromText: \" + line,\n\t\t\t\t\t\t\te);\n\t\t\t\t}\n\t\t\t\tif (sign == '-') {\n\t\t\t\t\t// Deletion.\n\t\t\t\t\tpatch.diffs.add(new Diff(Operation.DELETE, line));\n\t\t\t\t} else if (sign == '+') {\n\t\t\t\t\t// Insertion.\n\t\t\t\t\tpatch.diffs.add(new Diff(Operation.INSERT, line));\n\t\t\t\t} else if (sign == ' ') {\n\t\t\t\t\t// Minor equality.\n\t\t\t\t\tpatch.diffs.add(new Diff(Operation.EQUAL, line));\n\t\t\t\t} else if (sign == '@') {\n\t\t\t\t\t// Start of next patch.\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\t// WTF?\n\t\t\t\t\tthrow new IllegalArgumentException(\"Invalid patch mode '\" + sign + \"' in: \"\n\t\t\t\t\t\t\t+ line);\n\t\t\t\t}\n\t\t\t\ttext.removeFirst();\n\t\t\t}\n\t\t}\n\t\treturn patches;\n\t}\n\n\n\t/**\n\t * Class representing one diff operation.\n\t */\n\tpublic static class Diff {\n\t\t/**\n\t\t * One of: INSERT, DELETE or EQUAL.\n\t\t */\n\t\tpublic Operation operation;\n\t\t/**","sourceCodeStart":2345,"sourceCodeEnd":2381,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/util/diff/DiffMatchPatch.java#L2345-L2381","documentation":"While parsing diff lines inside a patch, patch_fromText expects each line to start with a mode character: ' ' (equal), '-' (delete), '+' (insert), or '@' (start of the next patch). Any other first character is unrecognized and triggers 'Invalid patch mode'. This prevents ambiguous or corrupted patch bodies from being silently misapplied.","triggerScenarios":"A line inside a patch body begins with a character other than ' ', '-', '+', or '@' — e.g. a line missing its mode prefix, a unified-diff line prefixed differently, or text accidentally concatenated into the patch body.","commonSituations":"Hand-editing patch text and dropping the leading +/- character; mixing standard unified diff output (lines like 'diff --git' or 'index ...') into patch_fromText input; copy/paste losing leading spaces at line starts.","solutions":["Check the offending line and add/restore the required mode prefix (' ', '-', or '+').","Do not feed raw unified diffs ('diff --git'/'index' lines) into patch_fromText; strip them or regenerate with patch_toText.","Re-encode patch lines so leading spaces survive transport (URL-encoding handles this); beware editors/HTML that trim leading spaces.","Wrap parsing in try-catch for IllegalArgumentException to reject corrupt patches cleanly."],"exampleFix":"// before\nString patch = \"@@ -1,1 +1,1 @@\\nhello\"; // missing mode char\n// after\nString patch = \"@@ -1,1 +1,1 @@\\n hello\"; // ' ' = context/equal line","handlingStrategy":"validation","validationCode":"boolean validPatchBody(java.util.List<String> lines) {\n    return lines.stream().skip(1) // skip header\n        .allMatch(l -> l.isEmpty() || \" +-@\".indexOf(l.charAt(0)) >= 0);\n}","typeGuard":null,"tryCatchPattern":"try {\n    patches = patch_fromText(text);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Invalid patch mode\")) { /* sanitize or reject */ }\n    else throw e;\n}","preventionTips":["Ensure every body line begins with ' ', '-', or '+'.","Strip non-patch lines (diff --git, index) before parsing.","Beware transports that strip leading spaces; keep URL-encoding intact."],"tags":["patch-parse","diff-match-patch","invalid-input-format"],"backgroundTag":"invalid-argument-format","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}