{"record":{"id":"12f60d248954a0ef","repo":"go-delve/delve","slug":"s-type-s-is-not-a-struct","errorCode":null,"errorMessage":"%s (type %s) is not a struct","messagePattern":"(.+?) \\(type (.+?)\\) is not a struct","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/eval.go","lineNumber":2110,"sourceCode":"\t\t}\n\n\t\tif v {\n\t\t\tbest = args[i]\n\t\t}\n\t}\n\n\tif best == nil {\n\t\treturn nil, fmt.Errorf(\"not enough arguments to %s\", name)\n\t}\n\treturn best, nil\n}\n\n// Evaluates expressions <subexpr>.<field name> where subexpr is not a package name\nfunc (scope *EvalScope) evalStructSelector(op *evalop.Select, stack *evalStack) {\n\txv := stack.pop()\n\t// Prevent abuse, attempting to call \"nil.member\" directly.\n\tif xv.Addr == 0 && xv.Name == \"nil\" {\n\t\tstack.err = fmt.Errorf(\"%s (type %s) is not a struct\", xv.Name, xv.TypeString())\n\t\treturn\n\t}\n\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) {","sourceCodeStart":2092,"sourceCodeEnd":2128,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/eval.go#L2092-L2128","documentation":"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.","triggerScenarios":"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.","commonSituations":"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'.","solutions":["Replace 'nil.<field>' with the intended variable or expression that holds the struct.","If testing for nil, compare instead: write '<expr> == nil' rather than selecting fields from nil.","Guard pointer dereferences in conditions: '<ptr> != nil && <ptr>.Field ...'.","Check the expression for typos where a real struct variable name was meant."],"exampleFix":"// before (breakpoint condition)\ncond 1 nil.next != nil\n// error: nil (type nil) is not a struct\n// after\ncond 1 p != nil && p.next != nil","handlingStrategy":"type-guard","validationCode":"// In a breakpoint condition, guard nil receivers:\n// p != nil && p.Field ...\n// In expression: never write 'nil.<field>'.","typeGuard":"// CLI-side guard before building a selector expression:\nif expr == \"nil\" || strings.HasPrefix(expr, \"nil.\") {\n    return errors.New(\"selector on nil literal is invalid\")\n}","tryCatchPattern":"res, err := scope.EvalExpression(selExpr, cfg)\nif err != nil && strings.Contains(err.Error(), \"is not a struct\") {\n    // expression selected a field on nil; rewrite the expression\n}","preventionTips":["never apply '.' to the literal nil","guard pointer dereferences in conditions with 'x != nil &&'","check for typos where a variable name was replaced by nil","use '== nil' comparisons to test for nil instead of field access"],"tags":["debugger","go","selector","nil-dereference"],"backgroundTag":"field-access-on-nil","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}