theonedev/onedev · critical · ExplicitException

%s (project id: %d, ref: %s)

Error message

%s (project id: %d, ref: %s)

What it means

Thrown by DefaultCommitInfoService while walking refs during commit info collection: a ref points to an object id that is missing from the object database (MissingObjectException), which JGit wraps into an ExplicitException annotated with the project id and ref name. It indicates repository corruption — a dangling ref referencing a pruned or never-delivered object.

Source

Thrown at server-core/src/main/java/io/onedev/server/xodus/DefaultCommitInfoService.java:984

					for (Object work : works) {
						if (work instanceof CollectingWork) {
							collectingWorks.add((CollectingWork) work);
						} else if (work instanceof CheckingWork) {
							try (RevWalk revWalk = new RevWalk(projectService.getRepository(projectId))) {
								Collection<Ref> refs = new ArrayList<>();
								refs.addAll(projectService.getRepository(projectId).getRefDatabase()
										.getRefsByPrefix(Constants.R_HEADS));
								refs.addAll(projectService.getRepository(projectId).getRefDatabase()
										.getRefsByPrefix(Constants.R_TAGS));

								for (Ref ref : refs) {
									RevObject revObj;
									try {
										revObj = revWalk.peel(revWalk.parseAny(ref.getObjectId()));
									} catch (MissingObjectException e) {
										var message = String.format("%s (project id: %d, ref: %s)", e.getMessage(),
												projectId, ref.getName());
										throw new ExplicitException(message);
									}
									if (revObj instanceof RevCommit) {
										RevCommit commit = (RevCommit) revObj;
										collectingWorks.add(new CollectingWork(CHECK_PRIORITY, commit.copy(),
												commit.getCommitTime(), ref.getName()));
									}
								}
							} catch (IOException e) {
								throw new RuntimeException(e);
							}
						}
					}
					collectingWorks.sort(new CommitTimeComparator());

					for (CollectingWork work : collectingWorks)
						doCollect(project, work.getCommitId(), work.getRefName());
				});
			}

View on GitHub (pinned to d44925c47c)

Solutions

  1. Delete or fix the offending ref (git update-ref -d <ref>) then re-run the operation.
  2. Run 'git fsck --full' on the project repository to enumerate all corruption.
  3. Re-fetch from the canonical remote to restore missing objects.
  4. Restore the repository from backup if corruption is extensive.

Example fix

// before
git update-ref refs/heads/broken refs/heads/broken
// after: remove ref pointing to missing object
git update-ref -d refs/heads/broken
git fetch origin '+refs/heads/*:refs/heads/*'
Defensive patterns

Strategy: try-catch

Try / catch

try { collectCommitInfo(projectId); } catch (ExplicitException e) { if (e.getMessage().contains("MissingObject")) repairRepository(projectId); }

Prevention

When it happens

Trigger: A ref (branch/tag) in the project's git repository points to a commit/tree/blob that does not exist in the pack files or loose objects — typically after interrupted gc/prune, failed fetch replication, or manual object deletion.

Common situations: Disk-full or killed 'git gc' left refs without objects; repository migrated/copied incompletely; fetch/prune removed objects a stale ref still targets; corrupted storage after crash.

Understand the failure class

Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.

Related errors


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