theonedev/onedev · error · IllegalStateException

Commits have already been marked as start.

Error message

Commits have already been marked as start.

What it means

RevWalk.assertNoCommitsMarkedStart() guards APIs (added in 5.5) that must be configured before any start commits exist. Once markStart/markUninteresting (roots) have been called, changing certain settings would invalidate the pending start set, so this IllegalStateException is thrown while roots is non-empty.

Source

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

	protected void assertNotStarted() {
		if (isNotStarted())
			return;
		throw new IllegalStateException(
				JGitText.get().outputHasAlreadyBeenStarted);
	}

	/**
	 * Throws an exception if any commits have been marked as start.
	 * <p>
	 * If {@link #markStart(RevCommit)} has already been called,
	 * {@link #reset()} can be called to satisfy this condition.
	 *
	 * @since 5.5
	 */
	protected void assertNoCommitsMarkedStart() {
		if (roots.isEmpty())
			return;
		throw new IllegalStateException(
				JGitText.get().commitsHaveAlreadyBeenMarkedAsStart);
	}

	private boolean isNotStarted() {
		return pending instanceof StartGenerator;
	}

	/**
	 * Create and return an {@link org.eclipse.jgit.revwalk.ObjectWalk} using
	 * the same objects.
	 * <p>
	 * Prior to using this method, the caller must reset this RevWalk to clean
	 * any flags that were used during the last traversal.
	 * <p>
	 * The returned ObjectWalk uses the same ObjectReader, internal object pool,
	 * and free RevFlags. Once the ObjectWalk is created, this RevWalk should
	 * not be used anymore.
	 *

View on GitHub (pinned to d44925c47c)

Solutions

  1. Move the configuration call above all markStart/markUninteresting invocations.
  2. Create a new RevWalk, configure first, then mark start commits.
  3. Refactor so start marking is the last step of walk setup.

Example fix

// before
walk.markStart(head);
walk.setRetainBody(false); // assertNoCommitsMarkedStart throws
// after
walk.setRetainBody(false);
walk.markStart(head);
Defensive patterns

Strategy: validation

Validate before calling

if (!walk.roots.isEmpty()) // roots are registered by markStart
    throw new IllegalStateException("mark start commits only after configuration");

Type guard

// structural guard: keep marking in one terminal method
void buildWalk(RevWalk w, Consumer<RevWalk> config, RevCommit... starts) throws IOException {
    config.accept(w); // all settings first
    for (RevCommit c : starts) w.markStart(c); // marking last
}

Try / catch

try {
    configure(walk);
} catch (IllegalStateException e) {
    walk = new RevWalk(repo);
    configure(walk);
    walk.markStart(head);
}

Prevention

When it happens

Trigger: Calling an API that asserts no start commits (e.g. setCommitSpooling mode or related pre-start configuration) after markStart(...) has already registered roots on the walk.

Common situations: Constructing a walk, marking start commits early, then applying late configuration; helper methods marking starts as a side effect before configuration code runs.

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/d2cbc0f85ab55bee. Report an issue: GitHub.