go-delve/delve · error
can not watch %q
Error message
can not watch %q
What it means
SetWatchpoint evaluates the given expression as an AST to find the watched variable's address. If the result has no address (Addr==0), a fake address, or no DWARF type, Delve cannot install a hardware watchpoint on it, so it returns this error naming the expression.
Source
Thrown at pkg/proc/breakpoints.go:734
}
// SetWatchpoint sets a data breakpoint at addr and stores it in the
// process wide break point table.
func (t *Target) SetWatchpoint(logicalID int, scope *EvalScope, expr string, wtype WatchType, cond ast.Expr) (*Breakpoint, error) {
if (wtype&WatchWrite == 0) && (wtype&WatchRead == 0) {
return nil, errors.New("at least one of read and write must be set for watchpoint")
}
n, err := parser.ParseExpr(expr)
if err != nil {
return nil, err
}
xv, err := scope.evalAST(n)
if err != nil {
return nil, err
}
if xv.Addr == 0 || xv.Flags&VariableFakeAddress != 0 || xv.DwarfType == nil {
return nil, fmt.Errorf("can not watch %q", expr)
}
if xv.Unreadable != nil {
return nil, fmt.Errorf("expression %q is unreadable: %v", expr, xv.Unreadable)
}
if xv.Kind == reflect.UnsafePointer || xv.Kind == reflect.Invalid {
return nil, fmt.Errorf("can not watch variable of type %s", xv.Kind.String())
}
// Special handling for interface types
if xv.Kind == reflect.Interface {
// For interfaces, we want to watch the data they point to
// Read the interface to get the data pointer
_, data, _ := xv.readInterface()
if xv.Unreadable != nil {
return nil, fmt.Errorf("error reading interface %q: %v", expr, xv.Unreadable)
}
if data == nil {
return nil, fmt.Errorf("invalid interface %q", expr)View on GitHub (pinned to a23773e6c3)
Solutions
- Watch an addressable variable stored in memory; take its address first if needed (e.g. watch *&x)
- Rebuild with -gcflags='all=-N -l' so locals are not optimized into registers and keep a stack address
- Ensure the binary retains DWARF debug info (no -w, not stripped)
- Restructure code to store the value of interest in a variable before watching it
Example fix
// before dlv: watch someFunc() // after val := someFunc() watch val // val is now an addressable memory variable
Defensive patterns
Strategy: validation
Validate before calling
xv, err := scope.EvalExpression(expr, LoadConfig{})
watchable := err == nil && xv.Addr != 0 && xv.DwarfType != nil && xv.Flags&proc.VariableFakeAddress == 0 Type guard
func watchable(v *proc.Variable) bool { return v != nil && v.Addr != 0 && v.DwarfType != nil && v.Flags&proc.VariableFakeAddress == 0 } Try / catch
bp, err := db.SetWatchpoint(0, 0, expr, Read, []string{})
if err != nil && strings.HasPrefix(err.Error(), "can not watch") {
return fmt.Errorf("expression %q is not an addressable variable; assign it to a local first", expr)
} Prevention
- Only watch local or heap variables that live at a memory address
- Rebuild with -gcflags='all=-N -l' to prevent register-allocation hiding variables
- Never watch literals, constants, or function call results directly
- Ensure the binary keeps DWARF type info (avoid -w/strip)
When it happens
Trigger: Calling SetWatchpoint with an expression that does not resolve to a concrete memory-resident variable: literals, register-allocated temporaries, composite expressions, package constants, or variables whose type info is missing.
Common situations: Watching an optimized-out local (kept in registers only, no stack address); watching 'x.y.z' where the intermediate was folded by the compiler; watching a constant or function return value instead of an addressable variable; missing DWARF type info due to stripped binary.
Related errors
- %s has no member %s
- %s (type %s) is not a struct
- break on read only not supported
- could not decode first frame
- unable to find function context
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/4375e17941b097b8.
Report an issue: GitHub.