{"record":{"id":"289b59f3677df886","repo":"JuliusBrussee/caveman","slug":"generic-target-q-requires-a-non-empty-source-path","errorCode":null,"errorMessage":"generic target %q requires a non-empty source path","messagePattern":"generic target %q requires a non-empty source path","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/importers/generic.go","lineNumber":99,"sourceCode":"\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) {\n\t// Try a bare array first.\n\tvar arr []map[string]any\n\tif err := json.Unmarshal(data, &arr); err == nil {\n\t\treturn arr, nil\n\t}\n\t// Then a {\"data\":[...]} wrapper.\n\tvar env struct {","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/shared/platform/importers/generic.go#L81-L117","documentation":"Thrown by validateGenericFieldMap (generic.go:99): a FieldMap entry has a known, valid target but its source path is empty after trimming. A target with no source path cannot resolve in any record, so it is rejected up front rather than failing later with the 'not found in any record' error. Both the target and its (empty) value would be meaningless.","triggerScenarios":"FieldMap contains e.g. {\"span_id\": \"\"} or {\"span_id\": \"   \"}; common when a config template defines all columns and some are left blank for the operator to fill, or when a YAML null deserializes as an empty string.","commonSituations":"Template configs with placeholder empty values never filled in; YAML keys with no value (key:) unmarshalling to \"\"; programmatic map building that sets a key before computing the path and never does; merge of config layers where one layer blanked the value.","solutions":["Fill in a real source path for the named target, or delete the entry entirely.","Guard your config loader: reject empty values for field-map entries before they reach the importer.","Watch YAML keys with no value - write key: \"\" explicitly or omit the key.","Re-run validateGenericFieldMap-equivalent checks locally before import."],"exampleFix":"# before (yaml)\nfield_map:\n  span_id:\n\n# after\nfield_map:\n  span_id: $.attributes.span.id","handlingStrategy":"validation","validationCode":"for target, path := range fieldMap {\n    if strings.TrimSpace(path) == \"\" {\n        return fmt.Errorf(\"target %q has an empty source path\", target)\n    }\n}","typeGuard":"func allPathsSet(m map[string]string) bool {\n    for _, v := range m { if strings.TrimSpace(v) == \"\" { return false } }\n    return true\n}","tryCatchPattern":"if err := importers.ImportGeneric(data, opts); err != nil {\n    return err // fill or remove the entry named in the message\n}","preventionTips":["Reject blank field-map values in your config loader.","Avoid YAML keys with no value; omit unused mappings entirely.","Lint field maps for empty strings before every import run."],"tags":["go","import","field-mapping","config","validation"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}