go-delve/delve · error · ErrShortRead
short read
Error message
short read
What it means
ErrShortRead is returned by the Windows native backend's ReadMemory when ReadProcessMemory succeeds but copies fewer bytes than the requested buffer size. Delve treats a partial read as an error because variable and instruction reads need the full requested span to be valid.
Source
Thrown at pkg/proc/native/threads_windows.go:125
if ok, err := t.dbp.Valid(); !ok {
return 0, err
}
if len(data) == 0 {
return 0, nil
}
var count uintptr
err := _WriteProcessMemory(t.dbp.os.hProcess, uintptr(addr), &data[0], uintptr(len(data)), &count)
if err != nil {
return 0, err
}
// On ARM64 the instruction and data caches are not coherent,
// WriteProcessMemory only updates the data cache so we must flush
// the instruction cache explicitly. On x86/amd64 this is a no-op.
_ = _FlushInstructionCache(t.dbp.os.hProcess, uintptr(addr), uintptr(len(data)))
return int(count), nil
}
var ErrShortRead = errors.New("short read")
func (t *nativeThread) ReadMemory(buf []byte, addr uint64) (int, error) {
if ok, err := t.dbp.Valid(); !ok {
return 0, err
}
if len(buf) == 0 {
return 0, nil
}
var count uintptr
err := _ReadProcessMemory(t.dbp.os.hProcess, uintptr(addr), &buf[0], uintptr(len(buf)), &count)
if err == nil && count != uintptr(len(buf)) {
err = ErrShortRead
}
return int(count), err
}
// SoftExc returns true if this thread received a software exception during the last resume.
func (t *nativeThread) SoftExc() bool {View on GitHub (pinned to a23773e6c3)
Solutions
- Check the pointer/address value being read for corruption before dereferencing it
- Reduce the requested read size or read page-by-page, stopping at the first failure
- Verify the target process is alive and the debug session is valid (dbp.Valid)
- Attach with sufficient privileges (SeDebugPrivilege) so all relevant pages are readable
Example fix
// before
n, err := thread.ReadMemory(buf, badPtr)
// after
n, err := thread.ReadMemory(buf, badPtr)
if err == proc.ErrShortRead {
buf = buf[:n] // use only the bytes actually read
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check: is the debugged process still valid?
// Delve checks internally via dbp.Valid(); from the RPC layer check process state first.
if !attached || processExited {
return fmt.Errorf("target not available")
} Type guard
func isShortRead(err error) bool {
return errors.Is(err, proc.ErrShortRead)
} Try / catch
n, err := thread.ReadMemory(buf, addr)
if errors.Is(err, proc.ErrShortRead) {
// use only the bytes that were read: buf[:n]
handlePartial(buf[:n])
return nil
} else if err != nil {
return err
} Prevention
- Validate pointers before reading (they may be garbage after corruption)
- Read in page-sized chunks and stop at the first failure
- Check target process liveness before memory operations
When it happens
Trigger: Any ReadMemory call on a Windows thread whose target address range crosses into unmapped or inaccessible memory, so ReadProcessMemory fills only part of buf and returns a short count.
Common situations: Reading past the end of a heap allocation or stack page, reading corrupted pointer values that point outside the process's mapped memory, or inspecting a target whose memory layout changed (process dying, guard pages).
Related errors
- NtQueryInformationThread failed: it returns 0x%x
- ErrMemoryReadUnavailable
- short read
- lldb backend not supported on Windows
- VirtualQueryEx wrapped around the address space or stuck
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/47a6a7ae13393c77.
Report an issue: GitHub.