{"record":{"id":"ef14e02592891826","repo":"apache/hadoop","slug":"stopwatch-is-already-stopped","errorCode":null,"errorMessage":"StopWatch is already stopped","messagePattern":"StopWatch is already stopped","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/StopWatch.java","lineNumber":73,"sourceCode":"   * Start to measure times and make the state of stopwatch running.\n   * @return this instance of StopWatch.\n   */\n  public StopWatch start() {\n    if (isStarted) {\n      throw new IllegalStateException(\"StopWatch is already running\");\n    }\n    isStarted = true;\n    startNanos = timer.monotonicNowNanos();\n    return this;\n  }\n\n  /**\n   * Stop elapsed time and make the state of stopwatch stop.\n   * @return this instance of StopWatch.\n   */\n  public StopWatch stop() {\n    if (!isStarted) {\n      throw new IllegalStateException(\"StopWatch is already stopped\");\n    }\n    long now = timer.monotonicNowNanos();\n    isStarted = false;\n    currentElapsedNanos += now - startNanos;\n    return this;\n  }\n\n  /**\n   * Reset elapsed time to zero and make the state of stopwatch stop.\n   * @return this instance of StopWatch.\n   */\n  public StopWatch reset() {\n    currentElapsedNanos = 0;\n    isStarted = false;\n    return this;\n  }\n\n  /**","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/StopWatch.java#L55-L91","documentation":"org.apache.hadoop.util.StopWatch.stop() throws IllegalStateException when the watch is not running: stop() without a prior start(), or a second stop() after the watch already halted. The elapsed accumulation (currentElapsedNanos) can only be advanced from a running state.","triggerScenarios":"watch.stop() in a finally block when start() was skipped or threw earlier; double-stop after an unconditional stop plus another teardown path; stop() called on a fresh or reset() watch.","commonSituations":"try/finally timing where start sits after the code that throws; loop bodies stopping per iteration but starting only once; close() implementations that stop a watch another layer already stopped.","solutions":["Check state: if (watch.isRunning()) watch.stop();","Ensure start() precedes the try block so finally's stop() always has a running watch","Centralize stop in one place (single owner) instead of multiple teardown paths","Use try-with-resources with the Closeable behavior (close stops a running watch safely)"],"exampleFix":"// before\ntry {\n  riskyInit();\n  watch.start();\n  doWork();\n} finally {\n  watch.stop();   // throws if riskyInit() failed before start\n}\n\n// after\nwatch.start();\ntry {\n  doWork();\n} finally {\n  if (watch.isRunning()) {\n    watch.stop();\n  }\n}","handlingStrategy":"validation","validationCode":"if (watch.isRunning()) {\n  watch.stop();\n}","typeGuard":null,"tryCatchPattern":"try { watch.stop(); } catch (IllegalStateException e) { /* was never started or already stopped: nothing to record */ }","preventionTips":["Place start() before the try block so finally's stop() always sees a running watch","Guard every stop() with isRunning() when multiple teardown paths exist","Prefer try-with-resources: close() stops a running watch without throwing","reset() after use so the next consumer starts from a stopped state"],"tags":["hadoop","stopwatch","timing","illegalstate","api-misuse"],"backgroundTag":"invalid-object-state","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}