{"record":{"id":"13ec09cd636aca55","repo":"MyCATApache/Mycat-Server","slug":"number-of-records-written-exceeded-numrecordstowri","errorCode":null,"errorMessage":"Number of records written exceeded numRecordsToWrite = ${numRecordsToWrite}","messagePattern":"Number of records written exceeded numRecordsToWrite = (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/memory/unsafe/utils/sort/UnsafeSorterSpillWriter.java","lineNumber":103,"sourceCode":"    writeBuffer[offset + 2] = (byte)(v >>>  8);\n    writeBuffer[offset + 3] = (byte)(v >>>  0);\n  }\n\n  /**\n   * Write a record to a spill file.\n   *\n   * @param baseObject the base object / memory page containing the record\n   * @param baseOffset the base offset which points directly to the record data.\n   * @param recordLength the length of the record.\n   * @param keyPrefix a sort key prefix\n   */\n  public void write(\n      Object baseObject,\n      long baseOffset,\n      int recordLength,\n      long keyPrefix) throws IOException {\n    if (numRecordsSpilled == numRecordsToWrite) {\n      throw new IllegalStateException(\n        \"Number of records written exceeded numRecordsToWrite = \" + numRecordsToWrite);\n    } else {\n      numRecordsSpilled++;\n    }\n\n    /**\n     * [# of records (int)] [[len (int)][prefix (long)][data (bytes)]...]\n     * 一条记录在文件中格式\n     * */\n\n      /**\n       * recordLength记录长度 4个bytes\n       */\n    writeIntToBuffer(recordLength, 0);\n    /**\n     * 排序key，8个bytes\n     */\n    writeLongToBuffer(keyPrefix, 4);","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/memory/unsafe/utils/sort/UnsafeSorterSpillWriter.java#L85-L121","documentation":"UnsafeSorterSpillWriter.write throws IllegalStateException once numRecordsSpilled has already reached numRecordsToWrite — the writer's contract is to spill exactly that many records, so an extra write() call means the spill accounting between sorter and writer is broken.","triggerScenarios":"Calling write(baseObject, baseOffset, recordLength, keyPrefix) more times than numRecordsToWrite for this spill file — usually when the sorter computes the record count before writing and then writes more records (concurrent inserts, wrong partition/page bounds).","commonSituations":"Concurrency bugs where records are inserted into the sorter while spilling is in progress; off-by-one or stale numRecordsToWrite when records were moved between sorter pages; custom code reusing a spent spill writer.","solutions":["Snapshot the record count (numRecordsToWrite) only after inserts are finished — stop mutating the sorter before spilling.","Verify the loop that writes records iterates exactly numRecordsToWrite times and stops at the correct page boundary.","Create a new spill writer for additional records instead of reusing one that hit its limit.","Add synchronization if inserts and spill can run concurrently."],"exampleFix":"// before\nsorter.insertRecord(ptr, prefix); // mutating during spill\nspillWriter.write(...);\n// after\nlong n = sorter.numRecords(); // freeze count first\nfor (long i = 0; i < n; i++) spillWriter.write(...); // no concurrent inserts","handlingStrategy":"validation","validationCode":"long expected = sorter.numRecords(); // freeze before spilling\nif (spillWriter.numRecordsSpilled() >= expected) return; // already done\nfor (long i = 0; i < expected; i++) spillWriter.write(...);","typeGuard":null,"tryCatchPattern":"try { spillWriter.write(base, offset, len, prefix); } catch (IllegalStateException e) { if (e.getMessage().startsWith(\"Number of records written exceeded\")) { log.error(\"spill accounting bug: extra record at {}\", offset); rotateSpillWriter(); } else throw e; }","preventionTips":["Freeze numRecordsToWrite before starting a spill","Never mutate sorter contents during a spill","Use a fresh writer per spill batch","Add assertions that write loops match the recorded count"],"tags":["spill","sorting","state-error"],"backgroundTag":"internal-invariant-violation","analyzedSha":"65f8d8beb752f935752f2a0eec0ab017facab9ef","analyzedAt":"2026-09-11T00:12:21.696Z","contentChangedAt":"2026-09-11T00:12:21.696Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}