go-delve/delve · error
failed to set xstate: %v
Error message
failed to set xstate: %v
What it means
ptraceSetXsave writes the thread's extended XSAVE state back with PT_SETXSTATE on FreeBSD/amd64. A non-zero return from ptrace is wrapped in this error. It means the kernel refused the xstate write (invalid buffer length, unsupported features in the buffer, or dead thread).
Source
Thrown at pkg/proc/native/ptrace_freebsd_amd64.go:62
// ptraceGetXsave gets the X86 XSAVE data for the given tid.
func ptraceGetXsave(tid int) ([]byte, error) {
len, err := ptraceXsaveLen(tid)
if err != nil {
return nil, err
}
xsaveBuf := make([]byte, len)
ret, err := C.ptrace(C.PT_GETXSTATE, C.pid_t(tid), C.caddr_t(unsafe.Pointer(&xsaveBuf[0])), C.int(len))
if ret != 0 {
return nil, fmt.Errorf("failed to get xstate: %v", err)
}
return xsaveBuf, nil
}
// ptraceSetXsave sets the X86 XSAVE data for the given tid.
func ptraceSetXsave(tid int, xsaveBuf []byte) error {
ret, err := C.ptrace(C.PT_SETXSTATE, C.pid_t(tid), C.caddr_t(unsafe.Pointer(&xsaveBuf[0])), C.int(len(xsaveBuf)))
if ret != 0 {
return fmt.Errorf("failed to set xstate: %v", err)
}
return nil
}
func ptraceGetRegset(id int) (*amd64util.AMD64Xstate, error) {
var regset amd64util.AMD64Xstate
ret, err := C.ptrace(C.PT_GETFPREGS, C.pid_t(id), C.caddr_t(unsafe.Pointer(®set.AMD64PtraceFpRegs)), C.int(0))
if ret != 0 {
return nil, fmt.Errorf("failed to get FP registers: %v", err)
}
regset.Xsave, err = ptraceGetXsave(id)
if err != nil {
return nil, err
}
err = amd64util.AMD64XstateRead(regset.Xsave, false, ®set, cpuid.AMD64XstateZMMHi256Offset())
return ®set, err
}
View on GitHub (pinned to a23773e6c3)
Solutions
- Confirm the target thread is alive before calling SetRegs-style register writes
- Ensure the xsave buffer length matches the CPU's xstate size (query once via PT_GETXSTATE and reuse that length)
- Upgrade/verify the FreeBSD kernel supports PT_SETXSTATE for the running CPU
- Capture errno properly if the formatted error is empty to identify the true cause
Example fix
// before
if regset.Xsave != nil {
return ptraceSetXsave(id, regset.Xsave)
}
// after
if regset.Xsave != nil {
if err := ptraceSetXsave(id, regset.Xsave); err != nil {
return fmt.Errorf("setxstate tid=%d: %w", id, err)
}
} Defensive patterns
Strategy: validation
Validate before calling
// before writing xstate
if !isThreadAlive(dbp, id) {
return fmt.Errorf("thread %d gone; skipping xstate write", id)
}
if len(xsaveBuf) != knownXstateSize {
return fmt.Errorf("xstate buffer %d != expected %d", len(xsaveBuf), knownXstateSize)
} Type guard
func isXstateWriteErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "failed to set xstate")
} Prevention
- Re-read the xstate (PT_GETXSTATE) immediately before modifying so buffer size/features match the CPU
- Write registers only while the thread is stopped and alive
- Test xstate write support once at attach; disable FP register editing if unsupported
When it happens
Trigger: ptraceSetRegset -> ptraceSetXsave when the xsave buffer size does not match what the kernel expects for the CPU's enabled xstate features, the tid has exited, or PT_SETXSTATE is unsupported by the running kernel.
Common situations: Setting registers after the debuggee thread died; kernel/CPU with different XSAVE feature set than the buffer captured earlier (e.g. after exec of a new binary); running in restricted environments (jails/VMs) lacking xstate write support.
Related errors
- failed to get xstate: %v
- failed to get xstate info: %v
- failed to get FP registers: %v
- failed to set FP registers: %v
- kinfo_getvmmap call failed
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/ff229e66bb51684b.
Report an issue: GitHub.