go-delve/delve · error

failed to set FP registers

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.

Solutions

  1. Verify the thread is stopped and alive before writing registers
  2. Re-fetch a fresh regset (PT_GETFPREGS), modify only needed fields, then write back
  3. Check ptrace permissions (root/same-UID, jail/securelevel constraints)
  4. 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

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


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

Appendix: 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(&regset.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, &regset, cpuid.AMD64XstateZMMHi256Offset())
	return &regset, 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(&regset.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)