{"record":{"id":"5294521a85e63af6","repo":"apache/beam","slug":"structx-inferfieldnames-of-non-struct-type-s","errorCode":null,"errorMessage":"structx: InferFieldNames of non-struct type %s","messagePattern":"structx: InferFieldNames of non-struct type (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/util/structx/struct.go","lineNumber":30,"sourceCode":"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Package structx provides utilities for working with structs.\npackage structx\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n)\n\n// InferFieldNames returns the field names of the given struct type and tag key. Includes only\n// exported fields. If a field's tag key is empty or not set, uses the field's name. If a field's\n// tag key is set to '-', omits the field. Panics if the type's kind is not a struct.\nfunc InferFieldNames(t reflect.Type, key string) []string {\n\tif t.Kind() != reflect.Struct {\n\t\tpanic(fmt.Sprintf(\"structx: InferFieldNames of non-struct type %s\", t))\n\t}\n\n\tvar names []string\n\n\tfor i := 0; i < t.NumField(); i++ {\n\t\tfield := t.Field(i)\n\n\t\tif field.Anonymous {\n\t\t\tnames = append(names, InferFieldNames(field.Type, key)...)\n\t\t\tcontinue\n\t\t}\n\n\t\tif !field.IsExported() {\n\t\t\tcontinue\n\t\t}\n\n\t\tvalue := field.Tag.Get(key)\n\t\tname := strings.Split(value, \",\")[0]","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/util/structx/struct.go#L12-L48","documentation":"structx.InferFieldNames reflects over a struct type to derive field names from tags. It documents that it panics when the passed reflect.Type's Kind is not reflect.Struct. Callers such as constructSelectStatement, inferProjection, and Read rely on this precondition, so passing any non-struct type immediately aborts.","triggerScenarios":"Passing a reflect.Type whose Kind is Slice, Map, Ptr, Int, etc. to InferFieldNames — e.g. calling it on reflect.TypeOf([]Row{}) or on a pointer type instead of the struct itself.","commonSituations":"Reading BigQuery rows / building projections with structx and accidentally passing reflect.TypeOf(&MyStruct{}) (pointer) or the element type of a slice; generic helpers that forward arbitrary types.","solutions":["Dereference pointer types before calling: use t.Elem() when t.Kind() == reflect.Ptr.","Pass the struct's value type, not a slice/map containing it (use the element type of a slice).","Guard the call with t.Kind() != reflect.Struct before invoking InferFieldNames.","Ensure your data model is a plain struct with exported fields when using structx-based readers."],"exampleFix":"// before\nnames := structx.InferFieldNames(reflect.TypeOf(&Row{}), \"beam\")\n// after\nt := reflect.TypeOf(&Row{})\nfor t != nil && t.Kind() == reflect.Ptr { t = t.Elem() }\nnames := structx.InferFieldNames(t, \"beam\")","handlingStrategy":"type-guard","validationCode":"t := reflect.TypeOf(v)\nfor t != nil && t.Kind() == reflect.Ptr { t = t.Elem() }\nif t == nil || t.Kind() != reflect.Struct {\n    return fmt.Errorf(\"structx needs a struct type, got %v\", t)\n}","typeGuard":"func isStructType(t reflect.Type) bool {\n    for t != nil && t.Kind() == reflect.Ptr { t = t.Elem() }\n    return t != nil && t.Kind() == reflect.Struct\n}","tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        if s, ok := r.(string); ok && strings.Contains(s, \"InferFieldNames of non-struct type\") {\n            log.Fatalf(\"structx misuse: %s\", s)\n        }\n        panic(r)\n    }\n}()","preventionTips":["Dereference pointers with t.Elem() before calling structx helpers","Use value types, not slices/maps, when deriving field names","Assert struct kind in shared helpers that feed structx","Prefer reflect.Indirect on values before passing types around"],"tags":["go","panic","reflection","structx"],"backgroundTag":"incompatible-source-type","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}