theonedev/onedev · error · IllegalArgumentException

Invalid patch string: ${text.getFirst()}

Error message

Invalid patch string: ${text.getFirst()}

What it means

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.

Source

Thrown at server-core/src/main/java/io/onedev/server/util/diff/DiffMatchPatch.java:2301

	 * @return List of Patch objects.
	 * @throws IllegalArgumentException If invalid input.
	 */
	public List<Patch> patch_fromText(String textline) throws IllegalArgumentException {
		List<Patch> patches = new LinkedList<Patch>();
		if (textline.length() == 0) {
			return patches;
		}
		List<String> textList = Arrays.asList(textline.split("\n"));
		LinkedList<String> text = new LinkedList<String>(textList);
		Patch patch;
		Pattern patchHeader = Pattern.compile("^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@$");
		Matcher m;
		char sign;
		String line;
		while (!text.isEmpty()) {
			m = patchHeader.matcher(text.getFirst());
			if (!m.matches()) {
				throw new IllegalArgumentException("Invalid patch string: " + text.getFirst());
			}
			patch = new Patch();
			patches.add(patch);
			patch.start1 = Integer.parseInt(m.group(1));
			if (m.group(2).length() == 0) {
				patch.start1--;
				patch.length1 = 1;
			} else if (m.group(2).equals("0")) {
				patch.length1 = 0;
			} else {
				patch.start1--;
				patch.length1 = Integer.parseInt(m.group(2));
			}

			patch.start2 = Integer.parseInt(m.group(3));
			if (m.group(4).length() == 0) {
				patch.start2--;
				patch.length2 = 1;

View on GitHub (pinned to d44925c47c)

Solutions

  1. Inspect the line named in the message and ensure the patch text starts with a valid header like '@@ -1,3 +1,4 @@'.
  2. Regenerate the patch string with DiffMatchPatch.patch_toText instead of hand-writing or hand-editing it.
  3. If patch text may be unreliable, wrap patch_fromText/patch_apply in try-catch for IllegalArgumentException and reject/repair the input.
  4. Verify the patch text was not altered in transit (trim trailing whitespace/newlines, check encoding, ensure no truncation).

Example fix

// before
String patchText = storedPatch.substring(storedPatch.indexOf('-')); // strips @@ header
dmp.patch_apply(dmp.patch_fromText(patchText), text);
// after
if (!storedPatch.trim().startsWith("@@")) {
    throw new IllegalArgumentException("Stored patch is missing its @@ header");
}
dmp.patch_apply(dmp.patch_fromText(storedPatch.trim()), text);
Defensive patterns

Strategy: try-catch

Validate before calling

boolean looksLikePatch(String s) {
    return s != null && s.trim().startsWith("@@");
}

Try / catch

try {
    LinkedList<String> lines = ...;
    patches = patch_fromText(lines);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Invalid patch string")) {
        // log offending line and reject/repair patch input
    } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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 @@.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/faa7f5b6ff8d6714. Report an issue: GitHub.