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(&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)

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.