{"record":{"id":"98f353681f577701","repo":"eclipse-vertx/vert.x","slug":"parsing-already-done","errorCode":null,"errorMessage":"Parsing already done","messagePattern":"Parsing already done","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"vertx-core/src/main/java/io/vertx/core/parsetools/impl/JsonParserImpl.java","lineNumber":168,"sourceCode":"  }\n\n  @Override\n  public void handle(Buffer data) {\n    byte[] bytes = data.getBytes();\n    try {\n      parser.feedInput(bytes, 0, bytes.length);\n    } catch (IOException e) {\n      handle(e);\n    }\n    checkTokens();\n    checkPending();\n    checkExceptions();\n  }\n\n  @Override\n  public void end() {\n    if (ended) {\n      throw new IllegalStateException(\"Parsing already done\");\n    }\n    ended = true;\n    parser.endOfInput();\n    checkTokens();\n    checkPending();\n    checkExceptions();\n  }\n\n  private void checkTokens() {\n    JsonLocation prevLocation = null;\n    while (true) {\n      JsonToken token;\n      try {\n        token = parser.nextToken();\n      } catch (IOException e) {\n        JsonLocation location = parser.currentLocation();\n        if (prevLocation != null) {\n          if (location.equals(prevLocation)) {","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java/io/vertx/core/parsetools/impl/JsonParserImpl.java#L150-L186","documentation":"JsonParser follows a stream lifecycle: once end() has been called the parse is complete and the instance cannot accept more input. Calling end() a second time throws IllegalStateException('Parsing already done'). The 'ended' flag is checked before signaling end-of-input to the underlying Jackson parser.","triggerScenarios":"Calling parser.end() twice, e.g. from both the stream endHandler and an explicit completion path; resuming a parser after completion to feed more buffers.","commonSituations":"Wiring the same parser to stream end and writeEnd(); retry logic that re-finishes a parser; framework adapters that may invoke end more than once on empty streams.","solutions":["Track ended state in your code and guard: if (!ended) parser.end()","Use end() in exactly one place — prefer the stream endHandler","Create a fresh JsonParser if a new document/stream must be parsed"],"exampleFix":"// before\nstream.endHandler(v -> parser.end());\n// later\nparser.end(); // IllegalStateException\n// after\nAtomicBoolean ended = new AtomicBoolean();\nstream.endHandler(v -> { if (ended.compareAndSet(false, true)) parser.end(); });","handlingStrategy":"validation","validationCode":"if (!ended.get()) {\n  parser.end();\n}","typeGuard":null,"tryCatchPattern":"try {\n  parser.end();\n} catch (IllegalStateException e) {\n  // already ended: safe to ignore\n}","preventionTips":["Call end() from exactly one code path (usually the stream endHandler)","Track ended state with an AtomicBoolean","Never reuse a JsonParser across streams — create a new one per document"],"tags":["vertx","json-parser","illegal-state","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"fb308bd8c3f12c79f4ae89bef67fadf6c80d036e","analyzedAt":"2026-09-06T11:37:12.241Z","contentChangedAt":"2026-09-06T11:37:12.241Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}