{"record":{"id":"50ac273eadb665c7","repo":"JuliusBrussee/caveman","slug":"generic-import-requires-a-non-empty-field-map","errorCode":null,"errorMessage":"generic import requires a non-empty field map","messagePattern":"generic import requires a non-empty field map","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/importers/generic.go","lineNumber":92,"sourceCode":"\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"generic record %d: %w\", i+1, err)\n\t\t}\n\t\tfor target := range resolved {\n\t\t\tresolvedTargets[target] = true\n\t\t}\n\t\trows = append(rows, sp)\n\t}\n\tfor target, path := range opts.FieldMap {\n\t\tif !resolvedTargets[target] {\n\t\t\treturn nil, fmt.Errorf(\"mapped source path %q for target %q was not found in any record\", path, target)\n\t\t}\n\t}\n\treturn rows, nil\n}\n\nfunc validateGenericFieldMap(fieldMap map[string]string) error {\n\tif len(fieldMap) == 0 {\n\t\treturn fmt.Errorf(\"generic import requires a non-empty field map\")\n\t}\n\tfor target, path := range fieldMap {\n\t\tif _, ok := genericTargets[target]; !ok {\n\t\t\treturn fmt.Errorf(\"unknown target column %q (not a caveman.spans column)\", target)\n\t\t}\n\t\tif strings.TrimSpace(path) == \"\" {\n\t\t\treturn fmt.Errorf(\"generic target %q requires a non-empty source path\", target)\n\t\t}\n\t}\n\tfor _, target := range []string{\"trace_id\", \"span_id\", \"timestamp\"} {\n\t\tif _, ok := fieldMap[target]; !ok {\n\t\t\treturn fmt.Errorf(\"generic import requires a %q mapping\", target)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc decodeGenericRecords(data []byte) ([]map[string]any, error) {","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/shared/platform/importers/generic.go#L74-L110","documentation":"Thrown by validateGenericFieldMap (generic.go:92): the generic importer was invoked with an empty (or nil) FieldMap. The field map is the entire definition of a generic import - it says which source path fills which caveman.spans column - so without it there is nothing to import and the call is refused up front, before any data is read.","triggerScenarios":"Constructing the generic import Options with FieldMap omitted, initialized as an empty map, or zeroed by a struct literal that forgets the field; also when a JSON/YAML config deserializes to an empty map because the key was misspelled.","commonSituations":"A new caller wiring the importer by copying a struct literal and dropping the map; configuration loaded from a file where 'fieldmap' vs 'field_map' key casing mismatched and unmarshalling silently left it empty; conditional code paths that build the map only in one branch.","solutions":["Populate Options.FieldMap with at least trace_id, span_id, and timestamp mappings (those are mandatory anyway).","Verify the config key spelling/casing that deserializes into FieldMap.","Fail fast at your call site when the map is empty, before invoking the importer.","See the genericTargets set in the same file for valid target names."],"exampleFix":"// before\nopts := importers.Options{} // FieldMap nil\n\n// after\nopts := importers.Options{FieldMap: map[string]string{\n  \"trace_id\": \"ctx.trace_id\",\n  \"span_id\":  \"ctx.span_id\",\n  \"timestamp\":\"ts\",\n}}","handlingStrategy":"validation","validationCode":"if len(fieldMap) == 0 {\n    return errors.New(\"refusing generic import: field map is empty\")\n}","typeGuard":"func isUsableFieldMap(m map[string]string) bool {\n    if len(m) == 0 { return false }\n    for _, t := range []string{\"trace_id\", \"span_id\", \"timestamp\"} {\n        if _, ok := m[t]; !ok { return false }\n    }\n    return true\n}","tryCatchPattern":"if err := importers.ImportGeneric(data, opts); err != nil {\n    return fmt.Errorf(\"import misconfigured: %w\", err)\n}","preventionTips":["Check config deserialization: a misspelled key yields an empty map silently.","Always include the three mandatory mappings (trace_id, span_id, timestamp).","Unit-test your Options construction against the importer's validation."],"tags":["go","import","config","field-mapping"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}