theonedev/onedev · error · IllegalStateException

Shallow commits have already been initialized.

Error message

Shallow commits have already been initialized.

What it means

RevWalk initializes shallow-commit information (from the repository's shallow file) at most once. initializeShallowCommits() throws IllegalStateException if shallowCommitsInitialized is already true, protecting against re-reading and duplicating shallow roots mid-walk.

Source

Thrown at server-core/src/main/java/org/eclipse/jgit/revwalk/RevWalk.java:1831

	 * There is a sequencing problem if the first commit being parsed is a
	 * shallow commit, since {@link RevCommit#parseCanonical(RevWalk, byte[])}
	 * calls this method before its callers add the new commit to the
	 * {@link RevWalk#objects} map. That means a call from this method to
	 * {@link #lookupCommit(AnyObjectId)} fails to find that commit and creates
	 * a new one, which is promptly discarded.
	 * <p>
	 * To avoid that, {@link RevCommit#parseCanonical(RevWalk, byte[])} passes
	 * its commit to this method, so that this method can apply the shallow
	 * state to it directly and avoid creating the duplicate commit object.
	 *
	 * @param rc
	 *            the initial commit being parsed
	 * @throws IOException
	 *             if the shallow commits file can't be read
	 */
	void initializeShallowCommits(RevCommit rc) throws IOException {
		if (shallowCommitsInitialized) {
			throw new IllegalStateException(
					JGitText.get().shallowCommitsAlreadyInitialized);
		}

		shallowCommitsInitialized = true;

		if (reader == null) {
			return;
		}

		for (ObjectId id : reader.getShallowCommits()) {
			if (id.equals(rc.getId())) {
				rc.parents = RevCommit.NO_PARENTS;
			} else {
				lookupCommit(id).parents = RevCommit.NO_PARENTS;
			}
		}
	}
}

View on GitHub (pinned to d44925c47c)

Solutions

  1. Do not call initializeShallowCommits directly; let RevWalk.parseCommit/parseAny trigger it once.
  2. Guard custom code with a flag before invoking it, or check walk.shallowCommitsInitialized state via subclass accessors.
  3. Use one RevWalk per thread; do not share walk instances across concurrent parsing.

Example fix

// before
walk.initializeShallowCommits(rc); // called for every parsed commit
// after
if (!shallowCommitsInitialized)
    walk.initializeShallowCommits(rc);
Defensive patterns

Strategy: try-catch

Validate before calling

// call at most once per walk instance
if (!initialized.getAndSet(true))
    walk.initializeShallowCommits(rc);

Type guard

AtomicBoolean shallowInit = new AtomicBoolean(false);
boolean shouldInit = shallowInit.compareAndSet(false, true);

Try / catch

try {
    walk.initializeShallowCommits(rc);
} catch (IllegalStateException e) {
    // already initialized - safe to ignore
}

Prevention

When it happens

Trigger: Internally triggered when commit parsing re-enters initializeShallowCommits after it already ran; direct callers (subclasses/tests) invoking it twice on the same walk; reusing a walk instance across shallow setups.

Common situations: Custom RevWalk subclasses that manually parse commits and call initializeShallowCommits unconditionally per commit; concurrency where two threads parse the first commit of a shallow clone simultaneously on one walk.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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