go-delve/delve · error
expression %q not an interface
Error message
expression %q not an interface
What it means
evalTypeAssert implements '<expr>.(<type>)' casts. A type assertion is only meaningful on interface values, so when the popped operand's reflect.Kind is not Interface, evaluation fails with 'expression %q not an interface'.
Source
Thrown at pkg/proc/eval.go:2131
// 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) {
xv := stack.pop()
if xv.Kind != reflect.Interface {
stack.err = fmt.Errorf("expression %q not an interface", astutil.ExprToString(op.Node.X))
return
}
xv.loadInterface(0, false, LoadFullValue())
if xv.Unreadable != nil {
stack.err = xv.Unreadable
return
}
if xv.Children[0].Unreadable != nil {
stack.err = xv.Children[0].Unreadable
return
}
if xv.Children[0].Addr == 0 {
stack.err = fmt.Errorf("interface conversion: %s is nil, not %s", xv.DwarfType.String(), astutil.ExprToString(op.Node.Type))
return
}
typ := op.DwarfType
if typ != nil && xv.Children[0].DwarfType.Common().Name != typ.Common().Name {
stack.err = fmt.Errorf("interface conversion: %s is %s, not %s", xv.DwarfType.Common().Name, xv.Children[0].TypeString(), typ.Common().Name)View on GitHub (pinned to a23773e6c3)
Solutions
- Remove the type assertion if the expression is already the concrete type and use it directly.
- If a conversion is intended, use Go conversion syntax T(x) instead of x.(T).
- Assert on the interface-typed expression instead, e.g. if the value is stored in an interface variable, write 'iface.(T)'.
- Use 'print <expr>' to inspect the static type (Kind) before writing the assertion.
Example fix
// before (x is declared as int) dlv> print x.(int) // error: expression "x" not an interface // after dlv> print x // already an int // or, if x is an interface: dlv> print x.(int)
Defensive patterns
Strategy: type-guard
Validate before calling
// Confirm the operand is an interface before asserting: // dlv> print x // shows the static type; if it's concrete, skip the assertion
Type guard
// Only build x.(T) when x's static type is an interface:
if v := eval(xExpr); v.Kind == reflect.Interface {
expr = fmt.Sprintf("%s.(%s)", xExpr, targetTypeName)
} else {
expr = xExpr // already concrete, use directly
} Try / catch
res, err := scope.EvalExpression(assertExpr, cfg)
if err != nil && strings.Contains(err.Error(), "not an interface") {
// use the value directly or convert with T(x) instead of x.(T)
} Prevention
- remember x.(T) is only for interfaces; T(x) is for conversions
- print the variable's static type before asserting
- in conditions, assert on interface-typed variables only
- avoid copy-pasting runtime assertions onto concrete-typed locals
When it happens
Trigger: Writing '<expr>.(T)' where <expr> evaluates to a concrete (non-interface) type — e.g. 'x.(int)' where x is already declared int — in a print/eval expression, breakpoint condition, or watchpoint.
Common situations: Copy-pasting runtime type assertions onto variables that the debugger already sees as concrete; confusing type assertions (x.(T)) with type conversions (T(x)); using assertions in bp conditions on concrete-typed locals.
Related errors
- interface conversion: %s is nil, not %s
- interface conversion: %s is %s, not %s
- invalid interface type
- can not convert value of type %s to %s: %v
- could not decode first frame
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/0ebf7afb866060a7.
Report an issue: GitHub.