theonedev/onedev · error · BlobEditException
Invalid old path: <oldPath>
Error message
Invalid old path: <oldPath>
What it means
The BlobEdits constructor normalizes every path in the oldPaths set via GitUtils.normalizePath, which returns null for paths that are invalid in git terms (empty, absolute, containing '..' or otherwise unnormalizable). If any old path fails normalization, a BlobEditException is thrown at construction time so a malformed edit set is never built.
Source
Thrown at server-core/src/main/java/io/onedev/server/git/BlobEdits.java:43
private static final long serialVersionUID = 1L;
private final Set<String> oldPaths;
private final Map<String, BlobContent> newBlobs;
public BlobEdits() {
this(new HashSet<>(), new HashMap<>());
}
public BlobEdits(Set<String> oldPaths, Map<String, BlobContent> newBlobs) {
this.oldPaths = new HashSet<>();
for (String oldPath: oldPaths) {
String normalizedPath = GitUtils.normalizePath(oldPath);
if (normalizedPath != null)
this.oldPaths.add(normalizedPath);
else
throw new BlobEditException("Invalid old path: " + oldPath);
}
this.newBlobs = new HashMap<>();
for (Map.Entry<String, BlobContent> entry: newBlobs.entrySet()) {
String normalizedPath = GitUtils.normalizePath(entry.getKey());
if (normalizedPath != null)
this.newBlobs.put(normalizedPath, entry.getValue());
else
throw new BlobEditException("Invalid new path: " + entry.getKey());
}
}
public Set<String> getOldPaths() {
return oldPaths;
}
public Map<String, BlobContent> getNewBlobs() {
return newBlobs;
}View on GitHub (pinned to d44925c47c)
Solutions
- Pass only normalized relative paths (no leading '/', no '..' segments, non-empty) in oldPaths.
- Run GitUtils.normalizePath on each path yourself before constructing BlobEdits and skip/reject null results.
- Catch BlobEditException and report which path was invalid to the caller.
- Sanitize user-supplied file paths in the API/UI layer before building edit sets.
Example fix
// before
new BlobEdits(Set.of("/src/../../etc/passwd"), Map.of()); // throws
// after
String p = GitUtils.normalizePath("/src/../../etc/passwd"); // null -> reject earlier
if (p != null) new BlobEdits(Set.of(p), Map.of()); Defensive patterns
Strategy: validation
Validate before calling
Set<String> safe = new HashSet<>();
for (String p : oldPaths) {
String n = GitUtils.normalizePath(p);
if (n == null) throw new IllegalArgumentException("Invalid old path: " + p);
safe.add(n);
} Type guard
boolean isValidGitPath(String p) {
return p != null && GitUtils.normalizePath(p) != null;
} Try / catch
try {
BlobEdits edits = new BlobEdits(oldPaths, newBlobs);
} catch (BlobEditException e) {
// report invalid path to caller
} Prevention
- Always use relative, '/'-separated paths without '..' segments.
- Normalize all paths with GitUtils.normalizePath before constructing BlobEdits.
- Reject absolute paths and empty strings at the input boundary.
- Treat any user-supplied path as untrusted and sanitize it.
When it happens
Trigger: new BlobEdits(oldPaths, newBlobs) where oldPaths contains an empty string, a path like "/abs/path", "../escape", or any string GitUtils.normalizePath cannot reduce to a valid relative path.
Common situations: REST/API callers deleting or moving files with absolute or '..'-containing paths; UI/API input not sanitized before constructing edit sets; paths with redundant or malformed segments that normalize to null.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- Invalid new path: <path>
- Specified path is not a directory: ${blobIdent.path}
- Specified path is not a file: ${blobIdent.path}
- Ref name is required when commit hash is specified
- Either commit hash, branch or tag should be specified
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/ccb6afc4f858650d.
Report an issue: GitHub.