MyCATApache/Mycat-Server · error · IllegalStateException

Number of records written exceeded numRecordsToWrite =

Error message

Number of records written exceeded numRecordsToWrite = ${numRecordsToWrite}

What it means

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.

Solutions

  1. Snapshot the record count (numRecordsToWrite) only after inserts are finished — stop mutating the sorter before spilling.
  2. Verify the loop that writes records iterates exactly numRecordsToWrite times and stops at the correct page boundary.
  3. Create a new spill writer for additional records instead of reusing one that hit its limit.
  4. Add synchronization if inserts and spill can run concurrently.

Example fix

// before
sorter.insertRecord(ptr, prefix); // mutating during spill
spillWriter.write(...);
// after
long n = sorter.numRecords(); // freeze count first
for (long i = 0; i < n; i++) spillWriter.write(...); // no concurrent inserts
Defensive patterns

Strategy: validation

Validate before calling

long expected = sorter.numRecords(); // freeze before spilling
if (spillWriter.numRecordsSpilled() >= expected) return; // already done
for (long i = 0; i < expected; i++) spillWriter.write(...);

Try / catch

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; }

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11). Data as JSON: /api/errors/13ec09cd636aca55. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/io/mycat/memory/unsafe/utils/sort/UnsafeSorterSpillWriter.java:103

    writeBuffer[offset + 2] = (byte)(v >>>  8);
    writeBuffer[offset + 3] = (byte)(v >>>  0);
  }

  /**
   * Write a record to a spill file.
   *
   * @param baseObject the base object / memory page containing the record
   * @param baseOffset the base offset which points directly to the record data.
   * @param recordLength the length of the record.
   * @param keyPrefix a sort key prefix
   */
  public void write(
      Object baseObject,
      long baseOffset,
      int recordLength,
      long keyPrefix) throws IOException {
    if (numRecordsSpilled == numRecordsToWrite) {
      throw new IllegalStateException(
        "Number of records written exceeded numRecordsToWrite = " + numRecordsToWrite);
    } else {
      numRecordsSpilled++;
    }

    /**
     * [# of records (int)] [[len (int)][prefix (long)][data (bytes)]...]
     * 一条记录在文件中格式
     * */

      /**
       * recordLength记录长度 4个bytes
       */
    writeIntToBuffer(recordLength, 0);
    /**
     * 排序key,8个bytes
     */
    writeLongToBuffer(keyPrefix, 4);

View on GitHub (pinned to 65f8d8beb7)