{"record":{"id":"11d89e622d3481fc","repo":"go-delve/delve","slug":"unhandled-case-existing-entry-is-v-len-v-new-i","errorCode":null,"errorMessage":"Unhandled case: existing entry is %v len %v, new is %v len %v","messagePattern":"Unhandled case: existing entry is (.+?) len (.+?), new is (.+?) len (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/core/core.go","lineNumber":93,"sourceCode":"\t\t\tadd(entry)\n\t\tcase off <= entry.offset && end < entryEnd:\n\t\t\t// New reader overwrites the beginning of the entry.\n\t\t\tif !inserted {\n\t\t\t\tadd(readerEntry{off, length, reader})\n\t\t\t\tinserted = true\n\t\t\t}\n\t\t\toverlap := entry.offset - off\n\t\t\tentry.offset += overlap\n\t\t\tentry.length -= overlap\n\t\t\tadd(entry)\n\t\tcase entry.offset < off && end < entryEnd:\n\t\t\t// New region punches a hole in the entry. Split it in two and put the new region in the middle.\n\t\t\tadd(readerEntry{entry.offset, off - entry.offset, entry.reader})\n\t\t\tadd(readerEntry{off, length, reader})\n\t\t\tadd(readerEntry{end + 1, entryEnd - end, entry.reader})\n\t\t\tinserted = true\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"Unhandled case: existing entry is %v len %v, new is %v len %v\", entry.offset, entry.length, off, length))\n\t\t}\n\t}\n\tif !inserted {\n\t\tnewReaders = append(newReaders, readerEntry{off, length, reader})\n\t}\n\tr.readers = newReaders\n}\n\n// ReadMemory implements MemoryReader.ReadMemory.\nfunc (r *SplicedMemory) ReadMemory(buf []byte, addr uint64) (n int, err error) {\n\tstarted := false\n\tfor _, entry := range r.readers {\n\t\tif entry.offset+entry.length <= addr {\n\t\t\tif !started {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn n, fmt.Errorf(\"hit unmapped area at %v after %v bytes\", addr, n)\n\t\t}","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/core/core.go#L75-L111","documentation":"Delve's core-dump backend maintains an ordered list of memory reader regions (spliced from core notes, loaded files, ELF segments). The 'add' helper in SplicedReader inserts a new reader region into the list, handling overlapping cases (replacing, prepending, appending, or punching a hole in an existing entry). When the new region overlaps an existing one in a way none of the switch cases cover, the default branch panics with the offsets and lengths of both entries, signaling a bug in the splice logic rather than bad user input.","triggerScenarios":"Adding a reader region to a spliced reader whose start/end partially straddles an existing entry in a combination not handled by the switch's named cases (equal-range replace, contained, superset, left-truncate, right-truncate, hole-split). Typically hit when a core file contains memory notes that overlap a mapped ELF segment in an unusual partial way, or when loaded extra-file regions overlap core memory.","commonSituations":"Opening a core/minidump file whose PT_NOTE memory regions overlap its PT_LOAD segments only partially; debugging a core from an unusual producer (older kernels, non-Go core generators, CRIU dumps); regression after changes to pkg/proc/core region merging.","solutions":["Inspect the panic message offsets/lengths and add a case (or generalize an existing case) in the splice switch to correctly handle that overlap combination","Dump the core file's memory notes and ELF segments (readelf -n / readelf -l) and check for partially overlapping regions that violate assumptions","Minimize with a failing test fixture core file reproducing the overlap, then fix the merge logic","Report upstream to go-delve/delve with the core file (or a sanitized reproduction) since this indicates an unhandled internal case"],"exampleFix":"// before\ndefault:\n    panic(fmt.Sprintf(\"Unhandled case: existing entry is %v len %v, new is %v len %v\", entry.offset, entry.length, off, length))\n// after\ndefault:\n    // Overlap not handled: fail gracefully instead of crashing.\n    return fmt.Errorf(\"splicedReader: unhandled overlap %v+%v vs %v+%v\", entry.offset, entry.length, off, length)","handlingStrategy":"validation","validationCode":"// Validate overlap shape before calling the splice logic:\nfunc overlapHandled(entryOff, entryLen, off, length uint64) bool {\n\tend, entryEnd := off+length-1, entryOff+entryLen-1\n\tswitch {\n\tcase off == entryOff && end == entryEnd: // full replace\n\t\treturn true\n\tcase off > entryOff && end < entryEnd: // contained\n\t\treturn true\n\tcase off <= entryOff && end >= entryEnd: // superset\n\t\treturn true\n\tcase off == entryEnd+1 || end == entryOff-1: // adjacent\n\t\treturn true\n\t}\n\treturn false\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Unit-test the splice switch with synthetic readerEntry slices covering every overlap combination","Test with real core files from multiple producers (kernel, rr, minidumps) whose notes overlap PT_LOAD segments partially","Convert the panic to an error return so malformed cores fail gracefully instead of crashing the session"],"tags":["core-dump","memory-regions","panic","splice"],"backgroundTag":"unhandled-overlap-case","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}