go-delve/delve · error

%s (type %s) is not a struct

Error message

%s (type %s) is not a struct

What it means

This error is raised by evalStructSelector when a field-access expression like <expr>.<field> is attempted on a value that is not a struct. Specifically it guards against the literal expression 'nil.member': when the popped variable has a zero address and Name "nil", Delve refuses the selector with this message.

Source

Thrown at pkg/proc/eval.go:2110

		}

		if v {
			best = args[i]
		}
	}

	if best == nil {
		return nil, fmt.Errorf("not enough arguments to %s", name)
	}
	return best, nil
}

// Evaluates expressions <subexpr>.<field name> where subexpr is not a package name
func (scope *EvalScope) evalStructSelector(op *evalop.Select, stack *evalStack) {
	xv := stack.pop()
	// Prevent abuse, attempting to call "nil.member" directly.
	if xv.Addr == 0 && xv.Name == "nil" {
		stack.err = fmt.Errorf("%s (type %s) is not a struct", xv.Name, xv.TypeString())
		return
	}
	// Prevent abuse, attempting to call "\"fake\".member" directly.
	if xv.Addr == 0 && xv.Name == "" && xv.DwarfType == nil && xv.RealType == nil {
		stack.err = fmt.Errorf("%s (type %s) is not a struct", xv.Value, xv.TypeString())
		return
	}
	// Special type conversions for CPU register variables (REGNAME.int8, etc)
	if xv.Flags&VariableCPURegister != 0 && !xv.loaded {
		stack.pushErr(xv.registerVariableTypeConv(op.Name))
		return
	}

	stack.pushErr(xv.findStructMemberOrMethod(op.Name, true))
}

// Evaluates expressions <subexpr>.(<type>)
func (scope *EvalScope) evalTypeAssert(op *evalop.TypeAssert, stack *evalStack) {

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Replace 'nil.<field>' with the intended variable or expression that holds the struct.
  2. If testing for nil, compare instead: write '<expr> == nil' rather than selecting fields from nil.
  3. Guard pointer dereferences in conditions: '<ptr> != nil && <ptr>.Field ...'.
  4. Check the expression for typos where a real struct variable name was meant.

Example fix

// before (breakpoint condition)
cond 1 nil.next != nil
// error: nil (type nil) is not a struct
// after
cond 1 p != nil && p.next != nil
Defensive patterns

Strategy: type-guard

Validate before calling

// In a breakpoint condition, guard nil receivers:
// p != nil && p.Field ...
// In expression: never write 'nil.<field>'.

Type guard

// CLI-side guard before building a selector expression:
if expr == "nil" || strings.HasPrefix(expr, "nil.") {
    return errors.New("selector on nil literal is invalid")
}

Try / catch

res, err := scope.EvalExpression(selExpr, cfg)
if err != nil && strings.Contains(err.Error(), "is not a struct") {
    // expression selected a field on nil; rewrite the expression
}

Prevention

When it happens

Trigger: Evaluating an expression such as 'nil.Foo' or 'nil.Field' at the debugger prompt (or in a breakpoint condition/watchpoint compiled through EvalExpression) where the receiver of '.' is the literal nil.

Common situations: Typing 'nil.member' accidentally instead of a variable name, or writing a breakpoint condition that dereferences nil, e.g. cond on a bp written as 'nil.next != nil'.

Related errors


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