{"record":{"id":"d22c9d88e2b092db","repo":"go-delve/delve","slug":"s-type-s-is-not-a-struct-d22c9d","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/variables.go","lineNumber":1194,"sourceCode":"\t\tif v.closureAddr != 0 {\n\t\t\tfn = v.bi.PCToFunc(v.Base)\n\t\t\tif fn != nil {\n\t\t\t\tcst := fn.extra(v.bi).closureStructType\n\t\t\t\tv = v.newVariable(v.Name, v.closureAddr, cst, v.mem)\n\t\t\t\tclosure = true\n\t\t\t}\n\t\t}\n\t}\n\n\tstructVar := v.maybeDereference()\n\tstructVar.Name = v.Name\n\tif structVar.Unreadable != nil {\n\t\treturn structVar, nil\n\t}\n\n\tt, isstruct := structVar.RealType.(*godwarf.StructType)\n\tif !isstruct {\n\t\treturn nil, fmt.Errorf(\"%s (type %s) is not a struct\", vname, structVar.TypeString())\n\t}\n\n\tfor _, field := range t.Field {\n\t\tif field.Name == memberName {\n\t\t\treturn structVar.toField(field)\n\t\t}\n\t\tif field.Name == \"&\"+memberName && closure {\n\t\t\tf, err := structVar.toField(field)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\treturn f.maybeDereference(), nil\n\t\t}\n\t}\n\n\treturn nil, fmt.Errorf(\"%s has no member %s\", vname, memberName)\n}\n","sourceCodeStart":1176,"sourceCodeEnd":1212,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/variables.go#L1176-L1212","documentation":"memberVariable found the parent expression but its real DWARF type is not a *godwarf.StructType, so field lookup cannot proceed. The expression treated a non-struct value as if it had fields.","triggerScenarios":"Evaluating 'x.field' where x's resolved type is a basic type, pointer that was not dereferenced, interface, or slice rather than a struct — so the StructType type assertion fails.","commonSituations":"Forgetting to dereference a pointer (need (*x).field or x.field only works via auto-deref for C-like access; in Delve use explicit deref), evaluating an interface without type assertion, typo making the expression resolve to a scalar.","solutions":["Check the actual type with 'print x' or x.TypeString() and fix the expression.","Explicitly dereference pointers: eval (*ptr).field.","Type-assert interfaces in the program or inspect the concrete value via iface.(data).","Ensure the binary is built without optimization so types resolve as written."],"exampleFix":"// before\ndlv> eval p.Name          // p is *Person\nCommand failed: p (type *main.Person) is not a struct\n\n// after\ndlv> eval (*p).Name","handlingStrategy":"type-guard","validationCode":"parent, err := client.EvalVariable(scope, vname, cfg)\nif err != nil { return err }\nif parent.Kind != reflect.Struct {\n    return fmt.Errorf(\"%s has kind %s; dereference or assert before field access\", vname, parent.Kind)\n}","typeGuard":"// Only evaluate x.field when x is really a struct value\nfunc isStructVar(v *api.Variable) bool { return v.Kind == reflect.Struct }\nif !isStructVar(parent) { return errors.New(\"not a struct; deref pointer first\") }","tryCatchPattern":"v, err := client.EvalVariable(scope, expr, cfg)\nif err != nil && strings.Contains(err.Error(), \"is not a struct\") {\n    // retry with explicit dereference: (*expr).field\n}","preventionTips":["Check types with `print` before field access","Explicitly dereference pointers in eval expressions","Build without optimization (-gcflags=all='-N -l') so declared types match runtime types"],"tags":["go","debugger","variables","types"],"backgroundTag":"not-a-struct","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}