{"record":{"id":"5f7b7922d2ee36c8","repo":"influxdata/influxdb","slug":"at-least-one-field-is-required-line","errorCode":null,"errorMessage":"At least one field is required: {line}","messagePattern":"At least one field is required: (.+?)","errorType":"validation","errorClass":"InvalidLineError","httpStatus":null,"severity":"error","filePath":"influxdb3_py_api/src/line_builder/line_builder.py","lineNumber":132,"sourceCode":"        self._timestamp_ns = timestamp_ns\n        return self\n\n    def build(self) -> str:\n        \"\"\"Build the line protocol string.\"\"\"\n        # Start with measurement name (escape commas and spaces)\n        line = self._escape_measurement(self.measurement)\n\n        # Add tags if present\n        if self.tags:\n            tags_str = \",\".join(\n                f\"{key}={self._escape_tag_value(value)}\"\n                for key, value in self.tags.items()\n            )\n            line += f\",{tags_str}\"\n\n        # Add fields (required)\n        if not self.fields:\n            raise InvalidLineError(f\"At least one field is required: {line}\")\n\n        fields_str = \",\".join(\n            f\"{self._escape_field_key(key)}={value}\"\n            for key, value in self.fields.items()\n        )\n        line += f\" {fields_str}\"\n\n        # Add timestamp if present\n        if self._timestamp_ns is not None:\n            line += f\" {self._timestamp_ns}\"\n\n        return line\n","sourceCodeStart":114,"sourceCodeEnd":145,"githubUrl":"https://github.com/influxdata/influxdb/blob/d28e26e048401c53cbb98cf2d6ab0cf1e98048ca/influxdb3_py_api/src/line_builder/line_builder.py#L114-L145","documentation":"LineBuilder.build() raises InvalidLineError when the builder has tags but no fields, because line protocol mandates at least one field set per line — a measurement with only tags is not a valid point. The message includes the partial line built so far (measurement + tags) to help identify the culprit. The check runs at serialization time, not when tags are added.","triggerScenarios":"LineBuilder('cpu').tag('host', 'a').build() — build() called before any uint64_field/int64_field/float64_field/string_field/bool_field call. Common when field addition is conditional and every branch skipped, or a refactor dropped the field line.","commonSituations":"Plugins that add fields per input record where some records carry no measurable values; loops that add tags eagerly but defer fields behind an 'if value is not None' that never fires; test code exercising tag-only construction.","solutions":["Ensure at least one field is added before build() — restructure so field addition is not skippable","Check len(builder.fields) > 0 (or 'if not builder.fields:') before calling build() and skip/log the empty point","Re-examine the record that produced no fields; a point with no field values has nothing to store in InfluxDB"],"exampleFix":"# before\nline = LineBuilder(\"cpu\").tag(\"host\", \"a\").build()  # InvalidLineError\n\n# after\nline = (\n    LineBuilder(\"cpu\")\n    .tag(\"host\", \"a\")\n    .float64_field(\"usage_user\", 42.0)\n    .build()\n)","handlingStrategy":"validation","validationCode":"if not builder.fields:\n    logger.warning(\"no fields for measurement %s; skipping point\", builder.measurement)\nelse:\n    line = builder.build()","typeGuard":null,"tryCatchPattern":"from influxdb3_py_api.line_builder import InvalidLineError\n\ntry:\n    line = builder.build()\nexcept InvalidLineError as e:\n    logger.warning(\"incomplete line: %s\", e)","preventionTips":["Always add at least one field before build(); make field addition non-conditional where possible","Assert builder.fields is non-empty in tests","Remember InfluxDB requires a field per point — tag-only points are not a thing"],"tags":["influxdb","line-protocol","python","fields","validation"],"backgroundTag":"line-protocol-validation","analyzedSha":"d28e26e048401c53cbb98cf2d6ab0cf1e98048ca","analyzedAt":"2026-08-16T19:53:34.623Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}