{"record":{"id":"0ebf7afb866060a7","repo":"go-delve/delve","slug":"expression-q-not-an-interface","errorCode":null,"errorMessage":"expression %q not an interface","messagePattern":"expression %q not an interface","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/eval.go","lineNumber":2131,"sourceCode":"\t// Prevent abuse, attempting to call \"\\\"fake\\\".member\" directly.\n\tif xv.Addr == 0 && xv.Name == \"\" && xv.DwarfType == nil && xv.RealType == nil {\n\t\tstack.err = fmt.Errorf(\"%s (type %s) is not a struct\", xv.Value, xv.TypeString())\n\t\treturn\n\t}\n\t// Special type conversions for CPU register variables (REGNAME.int8, etc)\n\tif xv.Flags&VariableCPURegister != 0 && !xv.loaded {\n\t\tstack.pushErr(xv.registerVariableTypeConv(op.Name))\n\t\treturn\n\t}\n\n\tstack.pushErr(xv.findStructMemberOrMethod(op.Name, true))\n}\n\n// Evaluates expressions <subexpr>.(<type>)\nfunc (scope *EvalScope) evalTypeAssert(op *evalop.TypeAssert, stack *evalStack) {\n\txv := stack.pop()\n\tif xv.Kind != reflect.Interface {\n\t\tstack.err = fmt.Errorf(\"expression %q not an interface\", astutil.ExprToString(op.Node.X))\n\t\treturn\n\t}\n\txv.loadInterface(0, false, LoadFullValue())\n\tif xv.Unreadable != nil {\n\t\tstack.err = xv.Unreadable\n\t\treturn\n\t}\n\tif xv.Children[0].Unreadable != nil {\n\t\tstack.err = xv.Children[0].Unreadable\n\t\treturn\n\t}\n\tif xv.Children[0].Addr == 0 {\n\t\tstack.err = fmt.Errorf(\"interface conversion: %s is nil, not %s\", xv.DwarfType.String(), astutil.ExprToString(op.Node.Type))\n\t\treturn\n\t}\n\ttyp := op.DwarfType\n\tif typ != nil && xv.Children[0].DwarfType.Common().Name != typ.Common().Name {\n\t\tstack.err = fmt.Errorf(\"interface conversion: %s is %s, not %s\", xv.DwarfType.Common().Name, xv.Children[0].TypeString(), typ.Common().Name)","sourceCodeStart":2113,"sourceCodeEnd":2149,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/eval.go#L2113-L2149","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (x is declared as int)\ndlv> print x.(int)\n// error: expression \"x\" not an interface\n// after\ndlv> print x        // already an int\n// or, if x is an interface:\ndlv> print x.(int)","handlingStrategy":"type-guard","validationCode":"// Confirm the operand is an interface before asserting:\n// dlv> print x        // shows the static type; if it's concrete, skip the assertion","typeGuard":"// Only build x.(T) when x's static type is an interface:\nif v := eval(xExpr); v.Kind == reflect.Interface {\n    expr = fmt.Sprintf(\"%s.(%s)\", xExpr, targetTypeName)\n} else {\n    expr = xExpr // already concrete, use directly\n}","tryCatchPattern":"res, err := scope.EvalExpression(assertExpr, cfg)\nif err != nil && strings.Contains(err.Error(), \"not an interface\") {\n    // use the value directly or convert with T(x) instead of x.(T)\n}","preventionTips":["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"],"tags":["debugger","go","type-assertion","interface"],"backgroundTag":"type-assertion-on-non-interface","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}