theonedev/onedev · error · NotAcceptableException
Specified path is not a file: ${blobIdent.path}
Error message
Specified path is not a file: ${blobIdent.path} What it means
RepositoryResource.getFile parses the 'revisionAndFile' path parameter into a BlobIdent and requires it to designate a file (blob). If the path points to a directory rather than a file, it throws a NotAcceptableException with message "Specified path is not a file: <path>".
Source
Thrown at server-core/src/main/java/io/onedev/server/rest/resource/RepositoryResource.java:357
return children;
}
@Api(order=100, description="Get metadata and content of specified file")
@Path("/{projectId}/files/{revisionAndFile:.*}")
@GET
public FileResponse getFile(
@PathParam("projectId") Long projectId,
@PathParam("revisionAndFile") @NotEmpty @Api(example="some-branch-or-tag/path/to/file") String revisionAndFile) {
Project project = projectService.load(projectId);
if (!SecurityUtils.canReadCode(project)) {
throw new UnauthorizedException();
}
List<String> revisionAndPathSegments = Splitter.on('/').splitToList(revisionAndFile);
BlobIdent blobIdent = new BlobIdent(project, revisionAndPathSegments);
if (!blobIdent.isFile()) {
throw new NotAcceptableException("Specified path is not a file: " + blobIdent.path);
}
Blob blob = project.getBlob(blobIdent, true);
FileResponse response = new FileResponse();
response.path = blobIdent.path;
response.sha = blob.getBlobId().name();
response.base64Content = new String(Base64.encodeBase64(blob.getBytes()));
response.size = blob.getSize();
response.isPartial = blob.isPartial();
return response;
}
@Api(order=110, description="Create, update, or delete specified file. Return hash of resulting commit",
example="46c001b04cba0ca41588841f1ca32f50b582ee9b")
@Path("/{projectId}/files/{branchAndFile:.*}")
@POST
public FileEditResponse editFile(View on GitHub (pinned to d44925c47c)
Solutions
- Append the exact file name to the path ('main/src/App.java' instead of 'main/src').
- Use getDirectory when you need the folder listing rather than file contents.
- Validate the target path resolves to a blob (e.g. via the directory listing) before requesting contents.
Example fix
// before curl .../projects/42/files/main/src // directory // after curl .../projects/42/files/main/src/App.java
Defensive patterns
Strategy: validation
Validate before calling
// ensure the path has a file segment before requesting contents
if (!revisionAndFile.includes("/") || pathEndsInDirectory(revisionAndFile)) {
throw new Error("Provide a full file path: revision/path/to/file");
} Type guard
function isFilePath(p) { return typeof p === "string" && /\.[A-Za-z0-9]+$/.test(p.split('/').pop() || ""); } Try / catch
try {
return await getFile(projectId, revisionAndFile);
} catch (e) {
if (isNotAcceptable(e) && /not a file/.test(e.message)) {
return await getDirectory(projectId, revisionAndFile); // it is a folder
}
throw e;
} Prevention
- Append the exact file name including extension to the revision.
- Use the directory endpoint when the target is a folder.
- Validate paths against a prior directory listing before fetching.
When it happens
Trigger: GET .../files/{revisionAndFile} where the path portion names a directory (e.g. 'main/src') instead of an actual file.
Common situations: Generic download-file scripts pointed at a folder URL; hardcoding paths that later became directories after refactoring; confusion between the file and directory endpoints.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Specified path is not a directory: ${blobIdent.path}
- Ref name is required when commit hash is specified
- Either commit hash, branch or tag should be specified
- Invalid old path: <oldPath>
- Invalid new path: <path>
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/6f283658aa646691.
Report an issue: GitHub.