{"record":{"id":"32cca0bfceeffbb4","repo":"theonedev/onedev","slug":"output-has-already-been-started","errorCode":null,"errorMessage":"Output has already been started.","messagePattern":"Output has already been started\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"server-core/src/main/java/org/eclipse/jgit/revwalk/RevWalk.java","lineNumber":1726,"sourceCode":"\t\t\t\tRevCommit r = next;\n\t\t\t\tnext = nextForIterator();\n\t\t\t\treturn r;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void remove() {\n\t\t\t\tthrow new UnsupportedOperationException();\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Throws an exception if we have started producing output.\n\t */\n\tprotected void assertNotStarted() {\n\t\tif (isNotStarted())\n\t\t\treturn;\n\t\tthrow new IllegalStateException(\n\t\t\t\tJGitText.get().outputHasAlreadyBeenStarted);\n\t}\n\n\t/**\n\t * Throws an exception if any commits have been marked as start.\n\t * <p>\n\t * If {@link #markStart(RevCommit)} has already been called,\n\t * {@link #reset()} can be called to satisfy this condition.\n\t *\n\t * @since 5.5\n\t */\n\tprotected void assertNoCommitsMarkedStart() {\n\t\tif (roots.isEmpty())\n\t\t\treturn;\n\t\tthrow new IllegalStateException(\n\t\t\t\tJGitText.get().commitsHaveAlreadyBeenMarkedAsStart);\n\t}\n","sourceCodeStart":1708,"sourceCodeEnd":1744,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/org/eclipse/jgit/revwalk/RevWalk.java#L1708-L1744","documentation":"Several RevWalk configuration methods (e.g. revSort, setTreeFilter, setRewriteParents, markStart-adjacent setup) call assertNotStarted(), which throws IllegalStateException once the walk has begun producing output (pending is no longer a StartGenerator). Configuration is immutable after iteration starts so in-flight generators are not invalidated.","triggerScenarios":"Calling revSort/setTreeFilter/filter/setRevFilter etc. after iterating the walk (even partially), after markStart, or reconfiguring a reused walk between traversals without resetting the generator state appropriately.","commonSituations":"Reusing a single RevWalk across requests and applying new filters after the first traversal; setting sort order inside a loop after calling next(); configuring in a finally block by mistake.","solutions":["Apply all filters, sorting and marking before the first next()/iterator() call.","Create a new RevWalk for each traversal instead of reconfiguring a started one.","Ensure no code path iterates (e.g. size/count helpers, stream().count()) before configuration completes."],"exampleFix":"// before\nwalk.markStart(head);\nwalk.next();\nwalk.sort(RevSort.REVERSE); // IllegalStateException\n// after\nwalk.sort(RevSort.REVERSE);\nwalk.markStart(head);\nwalk.next();","handlingStrategy":"validation","validationCode":"if (!walk.isNotStarted())\n    throw new IllegalStateException(\"configure the RevWalk before iterating\");\nwalk.sort(RevSort.COMMIT_TIME_DESC);","typeGuard":"boolean isConfigurable(RevWalk w) { return w.isNotStarted(); } // package-private; emulate by configuring before markStart","tryCatchPattern":"try {\n    walk.setRevFilter(filter);\n} catch (IllegalStateException e) {\n    walk = new RevWalk(repo); // fresh walk, reconfigure from scratch\n    walk.setRevFilter(filter);\n}","preventionTips":["Configure filters/sort before any markStart or iteration","Beware hidden iterations (stream().count(), size helpers)","Use a fresh RevWalk per traversal rather than reconfiguring"],"tags":["git","revwalk","illegal-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}