go-delve/delve · error

could not read %d bytes from address %#x: %v

Error message

could not read %d bytes from address %#x: %v

What it means

newCompositeMemory failed while reading the address-based piece of a DWARF location expression (op.AddrPiece): Reading piece.Size bytes at address piece.Val from the target memory failed. The wrapped error (from MemoryRead) carries the real cause, typically an unreadable/unmapped address.

Source

Thrown at pkg/proc/mem.go:152

	for i := range pieces {
		piece := &pieces[i]
		switch piece.Kind {
		case op.RegPiece:
			reg := regs.Bytes(piece.Val)
			if piece.Size == 0 && i == len(pieces)-1 {
				piece.Size = len(reg)
			}
			if piece.Size > len(reg) {
				if regs.FloatLoadError != nil {
					return nil, fmt.Errorf("could not read %d bytes from register %d (size: %d), also error loading floating point registers: %v", piece.Size, piece.Val, len(reg), regs.FloatLoadError)
				}
				return nil, fmt.Errorf("could not read %d bytes from register %d (size: %d)", piece.Size, piece.Val, len(reg))
			}
			cmem.data = append(cmem.data, reg[:piece.Size]...)
		case op.AddrPiece:
			buf := make([]byte, piece.Size)
			if _, err := mem.ReadMemory(buf, piece.Val); err != nil {
				return nil, fmt.Errorf("could not read %d bytes from address %#x: %v", piece.Size, piece.Val, err)
			}
			cmem.data = append(cmem.data, buf...)
		case op.ImmPiece:
			buf := piece.Bytes
			if buf == nil {
				sz := max(piece.Size, 8)
				if piece.Size == 0 && i == len(pieces)-1 {
					piece.Size = arch.PtrSize() // DWARF doesn't say what this should be
				}
				buf = make([]byte, sz)
				binary.LittleEndian.PutUint64(buf, piece.Val)
			}
			cmem.data = append(cmem.data, buf[:piece.Size]...)
		default:
			panic("unsupported piece kind")
		}
	}
	paddingBytes := int(size) - len(cmem.data)

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Read the wrapped %v cause — if it is an out-of-bounds/unmapped read, the variable's address is stale; move to a frame where the variable is live.
  2. Stop the process at a breakpoint before evaluating variables that live in memory.
  3. For core dumps, ensure the core covers the region (full core, not truncated).
  4. Re-check the binary matches the process/core (PIE base mismatch yields bogus addresses).

Example fix

// before: evaluating after function returned
state := <-continueCh
go eval("localVar")   // AddrPiece points to dead frame
// after: evaluate while stopped inside the frame
go eval("localVar")   // while breakpoint in the same frame is hit
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the piece address is in a mapped region before reading
for _, m := range procMemMap {
    if piece.Val >= m.Start && piece.Val+uint64(piece.Size) <= m.End { return nil }
}
return fmt.Errorf("address %#x not mapped", piece.Val)

Type guard

func addressMapped(addr uint64, size int, regions []MemoryRegion) bool {
    for _, r := range regions { if addr >= r.Start && addr+uint64(size) <= r.End { return true } }
    return false
}

Try / catch

v, err := scope.EvalVariable(name)
if err != nil && strings.Contains(err.Error(), "could not read ") && strings.Contains(err.Error(), "address 0x") {
    return fmt.Errorf("variable %s points to unreadable memory (stale frame?), stopped frame required: %w", name, err)
}

Prevention

When it happens

Trigger: CreateCompositeMemory on a location expression containing DW_OP_addr pieces pointing to memory that cannot be read — unmapped pages, freed heap, invalid stack address, or a detached/dead process.

Common situations: Evaluating a variable after its stack frame returned (address invalid); inspecting memory of a process that exited; address-space layout differences between core dump and live process; corrupt optimized code locations.

Related errors


AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31). Data as JSON: /api/errors/2be84f4070cfdfd7. Report an issue: GitHub.