go-delve/delve · error
failed to disassemble instruction: %w
Error message
failed to disassemble instruction: %w
What it means
Delve's dynamic-tracepoint callback (in traverse, used by eBPF follow-calls tracing) hits an indirect call at runtime and re-disassembles the single instruction at its PC to resolve the call destination. This error wraps any failure from proc.Disassemble for that one-instruction range. Because the static pass already disassembled the whole function successfully, failure here usually means memory at the PC is unreadable at callback time (process exited, memory unmapped) or the architecture backend could not decode the bytes.
Source
Thrown at service/debugger/debugger.go:1501
}
}
}
sdepth := rootindex + 1
if sdepth+1 > followCalls {
return false, nil
}
regs, err := th.Registers()
if err != nil {
return false, fmt.Errorf("registers inside callback returned err")
}
// Disassemble the instruction at the current PC to get the call destination
pc := instr.Loc.PC
maxInstLen := uint64(tgt.BinInfo().Arch.MaxInstructionLength())
disasm, err := proc.Disassemble(t.Memory(), regs, t.Breakpoints(), tgt.BinInfo(), pc, pc+maxInstLen)
if err != nil {
return false, fmt.Errorf("failed to disassemble instruction: %w", err)
}
// Extract address from the decoded instruction's destination location
var addr uint64
if len(disasm) > 0 && disasm[0].DestLoc != nil {
addr = disasm[0].DestLoc.PC
} else {
return false, fmt.Errorf("failed to extract call destination from instruction at PC %#x", pc)
}
fn := tgt.BinInfo().PCToFunc(addr)
if fn == nil {
return false, fmt.Errorf("PCToFunc returned nil")
}
err = createFunctionTracepoints(d, fn.Name, rootstr, followCalls)
if err != nil {
return false, fmt.Errorf("error creating tracepoint in function %s", fn.Name)
}
dynchildren, err := d.traverse(t, fn, sdepth+1, followCalls, rootstr)View on GitHub (pinned to a23773e6c3)
Solutions
- Re-run trace to rule out a transient failure caused by the target dying mid-trace (check with 'dlv attach' or process status first).
- Verify the traced binary is a complete, unstripped Go build (go build without -ldflags="-s -w").
- Confirm the eBPF backend supports your GOARCH; try tracing a smaller/caller function to isolate the failing call site.
- Reduce --follow-calls depth so fewer indirect call sites get dynamic breakpoints.
- If reproducible, file an issue with the PC value and the wrapped inner error from %w.
Example fix
// before (error surfaced with no context of which function)
return false, fmt.Errorf("failed to disassemble instruction: %w", err)
// after (add PC + function context to the wrap)
return false, fmt.Errorf("failed to disassemble instruction at PC %#x in %s: %w", pc, f.Name, err) Defensive patterns
Strategy: try-catch
Validate before calling
// before invoking dlv trace with eBPF follow-calls
dlvcmd := exec.Command("dlv", "trace", "--backend=ebpf", "--follow-calls=2", "--", "./mybin")
if err := dlvcmd.Run(); err != nil {
if strings.Contains(fmt.Sprint(err), "failed to disassemble instruction") {
log.Println("binary may be stripped or unsupported arch; rebuild unstripped for", runtime.GOARCH)
}
} Type guard
func isDisasmFailure(err error) bool {
return err != nil && strings.Contains(err.Error(), "failed to disassemble instruction")
} Try / catch
err := dlvCmd.Run()
var handled bool
if err != nil {
switch {
case isDisasmFailure(err):
// fall back to non-follow-calls tracing
handled = retryWithoutFollowCalls()
case isTransient(err):
handled = retryWithBackoff(3, time.Second, dlvCmd.Run)
}
if !handled {
log.Fatalf("trace failed: %v", err)
}
} Prevention
- Always trace unstripped binaries (avoid -ldflags "-s -w").
- Verify GOARCH is one Delve's eBPF backend supports before tracing.
- Keep the target process alive while tracepoints are installed.
- Test follow-calls tracing on a small function first to isolate call sites that fail.
When it happens
Trigger: Returned from the dynCallback breakpoint callback when proc.Disassemble(t.Memory(), regs, t.Breakpoints(), tgt.BinInfo(), pc, pc+maxInstLen) fails while resolving an indirect call (instr.IsCall() && instr.DestLoc == nil) during 'dlv trace --follow-calls' with the eBPF backend.
Common situations: Target process exited or its memory changed between setting the dynamic breakpoint and hitting it; attaching to a stripped/partially-mapped binary; architectures with limited disassembler support; tracing through cgo or JIT-ed code regions where PC points at non-Go memory.
Related errors
- disassemble failed with error %w
- failed to extract call destination from instruction at PC %#
- PCToFunc returned nil
- error calling traverse on dynamic children
- ebpf composite memory: %w
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/e7e1d2aee1c4d56a.
Report an issue: GitHub.