{"record":{"id":"faa7f5b6ff8d6714","repo":"theonedev/onedev","slug":"invalid-patch-string-text-getfirst","errorCode":null,"errorMessage":"Invalid patch string: ${text.getFirst()}","messagePattern":"Invalid patch string: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/util/diff/DiffMatchPatch.java","lineNumber":2301,"sourceCode":"\t * @return List of Patch objects.\n\t * @throws IllegalArgumentException If invalid input.\n\t */\n\tpublic List<Patch> patch_fromText(String textline) throws IllegalArgumentException {\n\t\tList<Patch> patches = new LinkedList<Patch>();\n\t\tif (textline.length() == 0) {\n\t\t\treturn patches;\n\t\t}\n\t\tList<String> textList = Arrays.asList(textline.split(\"\\n\"));\n\t\tLinkedList<String> text = new LinkedList<String>(textList);\n\t\tPatch patch;\n\t\tPattern patchHeader = Pattern.compile(\"^@@ -(\\\\d+),?(\\\\d*) \\\\+(\\\\d+),?(\\\\d*) @@$\");\n\t\tMatcher m;\n\t\tchar sign;\n\t\tString line;\n\t\twhile (!text.isEmpty()) {\n\t\t\tm = patchHeader.matcher(text.getFirst());\n\t\t\tif (!m.matches()) {\n\t\t\t\tthrow new IllegalArgumentException(\"Invalid patch string: \" + text.getFirst());\n\t\t\t}\n\t\t\tpatch = new Patch();\n\t\t\tpatches.add(patch);\n\t\t\tpatch.start1 = Integer.parseInt(m.group(1));\n\t\t\tif (m.group(2).length() == 0) {\n\t\t\t\tpatch.start1--;\n\t\t\t\tpatch.length1 = 1;\n\t\t\t} else if (m.group(2).equals(\"0\")) {\n\t\t\t\tpatch.length1 = 0;\n\t\t\t} else {\n\t\t\t\tpatch.start1--;\n\t\t\t\tpatch.length1 = Integer.parseInt(m.group(2));\n\t\t\t}\n\n\t\t\tpatch.start2 = Integer.parseInt(m.group(3));\n\t\t\tif (m.group(4).length() == 0) {\n\t\t\t\tpatch.start2--;\n\t\t\t\tpatch.length2 = 1;","sourceCodeStart":2283,"sourceCodeEnd":2319,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/util/diff/DiffMatchPatch.java#L2283-L2319","documentation":"DiffMatchPatch.patch_fromText parses a textual patch representation and expects each patch to begin with a header line matching patchHeader (e.g. '@@ -start1,len1 +start2,len2 @@'). If the first line of the remaining text does not match this header, the parser cannot determine where a patch starts, so it throws IllegalArgumentException. This guards against corrupted, truncated, or non-patch input being fed into the patch application pipeline.","triggerScenarios":"Calling DiffMatchPatch.patch_fromText (directly or via patch_apply) with text whose first line is not a valid '@@ -x,y +a,b @@' header: an empty header, hand-edited patch text, a patch with missing leading '@@' line, or concatenation of patch text with unrelated lines.","commonSituations":"Storing patches in files/DBs that get mangled (line endings, truncation); copying only the diff body without the @@ header; generating patch strings from a different diff library whose format differs; users pasting unified diffs with extra context lines before the first @@.","solutions":["Inspect the line named in the message and ensure the patch text starts with a valid header like '@@ -1,3 +1,4 @@'.","Regenerate the patch string with DiffMatchPatch.patch_toText instead of hand-writing or hand-editing it.","If patch text may be unreliable, wrap patch_fromText/patch_apply in try-catch for IllegalArgumentException and reject/repair the input.","Verify the patch text was not altered in transit (trim trailing whitespace/newlines, check encoding, ensure no truncation)."],"exampleFix":"// before\nString patchText = storedPatch.substring(storedPatch.indexOf('-')); // strips @@ header\ndmp.patch_apply(dmp.patch_fromText(patchText), text);\n// after\nif (!storedPatch.trim().startsWith(\"@@\")) {\n    throw new IllegalArgumentException(\"Stored patch is missing its @@ header\");\n}\ndmp.patch_apply(dmp.patch_fromText(storedPatch.trim()), text);","handlingStrategy":"try-catch","validationCode":"boolean looksLikePatch(String s) {\n    return s != null && s.trim().startsWith(\"@@\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    LinkedList<String> lines = ...;\n    patches = patch_fromText(lines);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Invalid patch string\")) {\n        // log offending line and reject/repair patch input\n    } else throw e;\n}","preventionTips":["Always produce patch strings via patch_toText, never by hand.","Validate patch text starts with '@@' before parsing.","Store/transfer patch text verbatim; watch for truncation and line-ending mangling."],"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-14T00:17:10.932Z"}