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
- 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.
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
- 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
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
- error while calling spill() on
- error while calling spill() on
- Comparison method violates its general contract!
- Not enough memory to grow pointer array
- There is no space for new record
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)