{"record":{"id":"79bc6c2377b5ea8c","repo":"VictoriaMetrics/VictoriaMetrics","slug":"missing-tags","errorCode":null,"errorMessage":"missing tags","messagePattern":"missing tags","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/protoparser/vmimport/parser.go","lineNumber":73,"sourceCode":"\tr.reset()\n\tv, err := tu.p.Parse(s)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cannot parse json line: %w\", err)\n\t}\n\n\t// Unmarshal tags\n\tmetric := v.GetObject(\"metric\")\n\tif metric == nil {\n\t\treturn fmt.Errorf(\"missing `metric` object\")\n\t}\n\ttagsStart := len(tu.tagsPool)\n\tif err := tu.unmarshalTags(metric); err != nil {\n\t\treturn fmt.Errorf(\"cannot unmarshal `metric`: %w\", err)\n\t}\n\ttags := tu.tagsPool[tagsStart:]\n\tr.Tags = tags[:len(tags):len(tags)]\n\tif len(r.Tags) == 0 {\n\t\treturn fmt.Errorf(\"missing tags\")\n\t}\n\n\t// Unmarshal values\n\tvalues := v.GetArray(\"values\")\n\tif len(values) == 0 {\n\t\treturn fmt.Errorf(\"missing `values` array\")\n\t}\n\tfor i, v := range values {\n\t\tf, err := v.Float64()\n\t\tif err != nil {\n\t\t\t// Fall back to parsing special values\n\t\t\tf, err = getSpecialFloat64(v)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"cannot unmarshal value at position %d: %w\", i, err)\n\t\t\t}\n\t\t}\n\t\tr.Values = append(r.Values, f)\n\t}","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/VictoriaMetrics/VictoriaMetrics/blob/5079fb58f1e8e62113f90c945ad71586c797d770/lib/protoparser/vmimport/parser.go#L55-L91","documentation":"This error comes from unmarshaling a single metric row in the VictoriaMetrics /api/v1/import JSON format. After successfully parsing the `metric` object's tags, the parser requires at least one tag; a row whose `metric` object produces zero tags (e.g. empty `{}` or a non-object metric) is rejected. Tags identify the time series, so a row without any tag cannot be stored.","triggerScenarios":"Posting JSON lines to /api/v1/import where a metric object is empty ({}), where the `metric` field is missing or not a JSON object, or where unmarshalTags succeeds but produces an empty tag list.","commonSituations":"Hand-written import payloads with placeholder `{}` metric objects; a client serializer dropping all tags when tag values are empty; batching code that builds rows from partially-filled structs where the tag map was never populated; format changes after upgrading VictoriaMetrics where `metric` was renamed.","solutions":["Ensure every row has a `metric` object with at least one key/value tag, e.g. {\"metric\":{\"__name__\":\"cpu\",\"host\":\"a\"},\"values\":[1],\"timestamps\":[1700000000000]}","Verify the client actually serializes the tags map (check it is not nil/empty before sending)","Log the offending payload line and re-send with corrected tags; consider adding a `__name__` tag if the series only had tags in a different field"],"exampleFix":"// before\n{\"metric\":{},\"values\":[1],\"timestamps\":[1700000000000]}\n// after\n{\"metric\":{\"__name__\":\"cpu_usage\",\"host\":\"node1\"},\"values\":[1],\"timestamps\":[1700000000000]}","handlingStrategy":"validation","validationCode":"// Go: validate rows before sending\nfor _, row := range rows {\n    if len(row.Tags) == 0 {\n        return fmt.Errorf(\"row %q has no tags; every metric needs at least one tag (e.g. __name__)\", row.MetricName)\n    }\n}","typeGuard":"func hasTags(m map[string]string) bool { return m != nil && len(m) > 0 }","tryCatchPattern":null,"preventionTips":["Always include at least __name__ plus identifying labels in the metric object","Assert tags non-empty in your batch builder before flush","Serialize from a typed struct so an empty map is obvious"],"tags":["json","victoriametrics","import","missing-tags"],"backgroundTag":"missing-tags","analyzedSha":"5079fb58f1e8e62113f90c945ad71586c797d770","analyzedAt":"2026-09-03T18:10:26.153Z","contentChangedAt":"2026-09-03T18:10:26.153Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}