theonedev/onedev · error · NotAcceptableException
Tag '${request.getTagName()}' already exists
Error message
Tag '${request.getTagName()}' already exists What it means
REST createTag checks project.getTagRef before creating and throws this conflict when a tag with the requested name already exists in the repository; permission to create that specific tag is verified first.
Source
Thrown at server-core/src/main/java/io/onedev/server/rest/resource/RepositoryResource.java:236
RefResponse response = new RefResponse();
response.refName = ref.getName();
response.commitHash = project.getRevCommit(ref.getObjectId(), true).getName();
return response;
}
@Api(order=70, description="Create a new tag")
@Path("/{projectId}/tags")
@POST
public Response createTag(@PathParam("projectId") Long projectId, @NotNull CreateTagRequest request) {
Project project = projectService.load(projectId);
if (!SecurityUtils.canCreateTag(project, request.getTagName())) {
throw new UnauthorizedException();
}
if (project.getTagRef(request.getTagName()) != null) {
throw new NotAcceptableException("Tag '" + request.getTagName() + "' already exists");
} else {
User user = SecurityUtils.getUser();
gitService.createTag(project, request.getTagName(), request.getRevision(), user.asPerson(),
request.getTagMessage(), project.isTagSignatureRequired(user, request.getTagName()));
}
return Response.ok().build();
}
@Api(order=80, description="Delete specified tag")
@Path("/{projectId}/tags/{tag:.*}")
@DELETE
public Response deleteTag(
@PathParam("projectId") Long projectId,
@PathParam("tag") @Api(example="test-tag") String tagName) {
Project project = projectService.load(projectId);
if (!SecurityUtils.canDeleteTag(project, tagName)) {
throw new UnauthorizedException();View on GitHub (pinned to d44925c47c)
Solutions
- Use a new version/tag name
- Delete the existing tag first (if permitted) then recreate it
- Make automation idempotent: check GET /~api/{projectId}/tags/{tag} before POST and skip if 200
- Fix version numbering scheme to avoid duplicate releases
Example fix
// before
POST /~api/1/tags {"tagName":"v1.0","revision":"main"} // already exists
// after
POST /~api/1/tags {"tagName":"v1.0.1","revision":"main"} Defensive patterns
Strategy: validation
Validate before calling
let exists = false;
try { await api.get(`/projects/${id}/tags/${tagName}`); exists = true; } catch (e) {}
if (exists) throw new Error(`tag ${tagName} already exists`); Try / catch
try {
createTag(projectId, req);
} catch (NotAcceptableException e) {
// treat as idempotent or bump version
} Prevention
- Check tag existence before creating
- Make release pipelines idempotent on retry
- Enforce unique version numbers in CI
When it happens
Trigger: Calling POST /~api/{projectId}/tags with a tagName that already resolves to an existing ref (e.g. re-running a release job for an already-cut version).
Common situations: Re-running a failed release pipeline that already created the tag; re-releasing the same version number; collision between automated and manual tagging.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- Branch '${request.getBranchName()}' already exists
- Tag not found: ${tagName}
- Ref name should start with refs/
- Specified commit is not reachable from specified ref
- Branch not found: ${branchName}
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/2160a45e2fa34de3.
Report an issue: GitHub.