go-delve/delve · error
failed to set FP registers: %v
Error message
failed to set FP registers: %v
What it means
ptraceSetRegset writes the FP register block with PT_SETFPREGS on FreeBSD/amd64, then optionally the xstate via PT_SETXSTATE. Failure of PT_SETFPREGS is wrapped as 'failed to set FP registers'. The kernel rejected the FP state write for this thread.
Source
Thrown at pkg/proc/native/ptrace_freebsd_amd64.go:84
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
}
func ptraceSetRegset(id int, regset *amd64util.AMD64Xstate) error {
ret, err := C.ptrace(C.PT_SETFPREGS, C.pid_t(id), C.caddr_t(unsafe.Pointer(®set.AMD64PtraceFpRegs)), C.int(0))
if ret != 0 {
return fmt.Errorf("failed to set FP registers: %v", err)
}
if regset.Xsave != nil {
return ptraceSetXsave(id, regset.Xsave)
}
return nil
}
View on GitHub (pinned to a23773e6c3)
Solutions
- Verify the thread is stopped and alive before writing registers
- Re-fetch a fresh regset (PT_GETFPREGS), modify only needed fields, then write back
- Check ptrace permissions (root/same-UID, jail/securelevel constraints)
- If the write races with thread exit, detect ESRCH and treat as thread-dead rather than retrying blindly
Defensive patterns
Strategy: validation
Validate before calling
// ensure thread stopped and alive before write
if !isThreadAlive(dbp, id) {
return fmt.Errorf("thread %d exited; cannot set FP registers", id)
}
if !isStopped(dbp) {
return fmt.Errorf("process must be stopped to set registers")
} Try / catch
if err := ptraceSetRegset(id, regset); err != nil {
if strings.Contains(err.Error(), "failed to set FP registers") {
// refresh regset from the live thread and retry once
fresh, ferr := ptraceGetRegset(id)
if ferr == nil {
return ptraceSetRegset(id, fresh)
}
}
return err
} Prevention
- Always write a regset freshly read from the same thread
- Only write registers while the target is stopped
- Check for ESRCH and drop the thread from the cache on failure
When it happens
Trigger: Calling register-setting APIs (e.g. nativeThread.SetReg on FP/SSE registers, SetPC paths that restore full state) on a dead/stale tid, with a malformed regset, or without ptrace permission.
Common situations: Setting FP registers after the debuggee thread exited; hardware/kernel mismatch making the FP area invalid; writing while the process is not in a stopped state acceptable to ptrace.
Related errors
- failed to get FP registers: %v
- failed to get xstate info: %v
- failed to get xstate: %v
- failed to set xstate: %v
- procstat_getprocs returned no processes
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/8a2509bc3f051cfd.
Report an issue: GitHub.