go-delve/delve · error

wrong number of bytes for register %s (%d)

Error message

wrong number of bytes for register %s (%d)

What it means

On Windows (amd64), when writing register values back to a thread's CONTEXT, Delve requires each general-purpose register slot to hold exactly 8 bytes. A Register with a non-nil Bytes field of length other than 8 is rejected.

Source

Thrown at pkg/proc/winutil/regs_amd64_arch.go:332

	case regnum.AMD64_R10:
		p = &ctx.R10
	case regnum.AMD64_R11:
		p = &ctx.R11
	case regnum.AMD64_R12:
		p = &ctx.R12
	case regnum.AMD64_R13:
		p = &ctx.R13
	case regnum.AMD64_R14:
		p = &ctx.R14
	case regnum.AMD64_R15:
		p = &ctx.R15
	case regnum.AMD64_Rip:
		p = &ctx.Rip
	}

	if p != nil {
		if reg.Bytes != nil && len(reg.Bytes) != 8 {
			return fmt.Errorf("wrong number of bytes for register %s (%d)", regnum.AMD64ToName(regNum), len(reg.Bytes))
		}
		*p = reg.Uint64Val
	} else if regNum == regnum.AMD64_Rflags {
		ctx.EFlags = uint32(reg.Uint64Val)
	} else {
		if regNum < regnum.AMD64_XMM0 || regNum > regnum.AMD64_XMM0+15 {
			return fmt.Errorf("can not set register %s", regnum.AMD64ToName(regNum))
		}
		reg.FillBytes()
		if len(reg.Bytes) > 16 {
			return fmt.Errorf("too many bytes when setting register %s", regnum.AMD64ToName(regNum))
		}
		copy(ctx.FltSave.XmmRegisters[(regNum-regnum.AMD64_XMM0)*16:], reg.Bytes)
	}
	return nil
}

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Ensure reg.Bytes is exactly 8 bytes (or nil so only Uint64Val is used) before setting an amd64 general-purpose register
  2. Call reg.FillBytes() (as the code does for XMM) to materialize Bytes from Uint64Val, then pad/truncate to 8
  3. Verify you are not reusing register values read from a 386/x86 (4-byte) context on an amd64 target
  4. Use the documented RPC SetRegister path instead of hand-building winutil Register structs

Example fix

// before
reg := winutil.Register{RegNum: regnum.AMD64_Rax, Bytes: []byte{1,2,3,4}} // 4 bytes -> error
// after
reg := winutil.Register{RegNum: regnum.AMD64_Rax}
reg.Uint64Val = 0x4141414141414141
reg.FillBytes() // Bytes now len 8
Defensive patterns

Strategy: validation

Validate before calling

// Before writing a GP register on Windows amd64:
if reg.Bytes != nil && len(reg.Bytes) != 8 {
    reg.FillBytes(); reg.Bytes = reg.Bytes[:8] // normalize
}

Type guard

func validGPReg(reg winutil.Register) bool {
    return reg.Bytes == nil || len(reg.Bytes) == 8
}

Prevention

When it happens

Trigger: Calling SetRegs/WriteRegisters (e.g. via a debugger client setting a register) with a Register whose Bytes slice was populated with a length != 8, such as a 4-byte value from a 32-bit-style read or a truncated buffer.

Common situations: Custom tooling that constructs Register structs by hand for Windows targets; mixing register data captured from a different architecture; partial register writes where only low bytes were captured.

Related errors


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