theonedev/onedev · error · IllegalArgumentException

Invalid patch mode '${sign}' in: ${line}

Error message

Invalid patch mode '${sign}' in: ${line}

What it means

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.

Source

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

					// Malformed URI sequence.
					throw new IllegalArgumentException("Illegal escape in patch_fromText: " + line,
							e);
				}
				if (sign == '-') {
					// Deletion.
					patch.diffs.add(new Diff(Operation.DELETE, line));
				} else if (sign == '+') {
					// Insertion.
					patch.diffs.add(new Diff(Operation.INSERT, line));
				} else if (sign == ' ') {
					// Minor equality.
					patch.diffs.add(new Diff(Operation.EQUAL, line));
				} else if (sign == '@') {
					// Start of next patch.
					break;
				} else {
					// WTF?
					throw new IllegalArgumentException("Invalid patch mode '" + sign + "' in: "
							+ line);
				}
				text.removeFirst();
			}
		}
		return patches;
	}


	/**
	 * Class representing one diff operation.
	 */
	public static class Diff {
		/**
		 * One of: INSERT, DELETE or EQUAL.
		 */
		public Operation operation;
		/**

View on GitHub (pinned to d44925c47c)

Solutions

  1. Check the offending line and add/restore the required mode prefix (' ', '-', or '+').
  2. Do not feed raw unified diffs ('diff --git'/'index' lines) into patch_fromText; strip them or regenerate with patch_toText.
  3. Re-encode patch lines so leading spaces survive transport (URL-encoding handles this); beware editors/HTML that trim leading spaces.
  4. Wrap parsing in try-catch for IllegalArgumentException to reject corrupt patches cleanly.

Example fix

// before
String patch = "@@ -1,1 +1,1 @@\nhello"; // missing mode char
// after
String patch = "@@ -1,1 +1,1 @@\n hello"; // ' ' = context/equal line
Defensive patterns

Strategy: validation

Validate before calling

boolean validPatchBody(java.util.List<String> lines) {
    return lines.stream().skip(1) // skip header
        .allMatch(l -> l.isEmpty() || " +-@".indexOf(l.charAt(0)) >= 0);
}

Try / catch

try {
    patches = patch_fromText(text);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Invalid patch mode")) { /* sanitize or reject */ }
    else throw e;
}

Prevention

When it happens

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

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

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/766941fb3073377c. Report an issue: GitHub.