{"record":{"id":"976fd04976221a1f","repo":"vitessio/vitess","slug":"expected-a-named-type-for-s-got-v","errorCode":null,"errorMessage":"expected a named type for %s, got %v","messagePattern":"expected a named type for (.+?), got (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtctl/vtctldclient/codegen/main.go","lineNumber":358,"sourceCode":"\t}\n\n\treturn nil, fmt.Errorf(\"symbol %s was not an interface but %T\", name, obj.Type())\n}\n\nvar vitessProtoRegexp = regexp.MustCompile(`^vitess\\.io.*/proto/.*`)\n\nfunc rewriteProtoImports(pkg *types.Package) string {\n\tif vitessProtoRegexp.MatchString(pkg.Path()) {\n\t\treturn pkg.Name() + \"pb\"\n\t}\n\n\treturn pkg.Name()\n}\n\nfunc extractLocalNamedType(v *types.Var) (name string, localImport string, pkgPath string, argImports []typeArgImport, err error) {\n\tnamed, ok := v.Type().(*types.Named)\n\tif !ok {\n\t\treturn \"\", \"\", \"\", nil, fmt.Errorf(\"expected a named type for %s, got %v\", v.Name(), v.Type())\n\t}\n\n\ttypeArgs, argImports, err := renderTypeArgs(named)\n\tif err != nil {\n\t\treturn \"\", \"\", \"\", nil, err\n\t}\n\n\tname = named.Obj().Name() + typeArgs\n\tlocalImport = rewriteProtoImports(named.Obj().Pkg())\n\tpkgPath = named.Obj().Pkg().Path()\n\n\treturn name, localImport, pkgPath, argImports, nil\n}\n\n// typeArgImport describes an import required by a type argument of an\n// instantiated generic type.\ntype typeArgImport struct {\n\tlocalImport string","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtctl/vtctldclient/codegen/main.go#L340-L376","documentation":"extractLocalNamedType expects each *types.Var (a function/method parameter) to have a named type so the generator can map it to a local proto import and render type arguments. This error means the parameter's type is unnamed (basic type, slice, map, unnamed struct, or unnamed pointer target chain), which the template generator does not support.","triggerScenarios":"The source interface being processed has a method whose parameter is not a named type or *types.Named generic instantiation — e.g. takes a string, []byte, map[K]V, or a non-generic unnamed type.","commonSituations":"Adding a method to the source interface with primitive/composite parameters and then running vtctldclient codegen; changing a method signature to use context.Context-style unnamed generics or plain types the codegen does not handle; the anonymous <anonymous> caller path is when renderTypeArgs or the main flow processes a var from a method signature.","solutions":["Change the interface method parameter to a named type (e.g. a proto message pointer or named generic instantiation)","If the parameter must stay primitive, extend the codegen tool to handle that type kind","Revert recent signature changes to the interface before running codegen"],"exampleFix":"// before\nDoThing(ctx context.Context, names map[string]string) error\n// after\nDoThing(ctx context.Context, req *vtctldatapb.DoThingRequest) error\n","handlingStrategy":"validation","validationCode":"// Audit interface method params for named types before codegen\nfor i := 0; i < sig.Params().Len(); i++ {\n    if _, ok := sig.Params().At(i).Type().(*types.Named); !ok {\n        return fmt.Errorf(\"param %d of %s is not a named type\", i, fn)\n    }\n}","typeGuard":"func isNamedParam(v *types.Var) bool {\n    _, ok := v.Type().(*types.Named)\n    return ok\n}","tryCatchPattern":null,"preventionTips":["Keep interface method params as proto message types or named generic instantiations","Run codegen immediately after signature edits so failures map to the recent change"],"tags":["go","codegen","type-system","generics"],"backgroundTag":"unsupported-parameter-type","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}