{"record":{"id":"753d7a18b1a3bcce","repo":"influxdata/influxdb","slug":"measurement-name-cannot-contain-spaces","errorCode":null,"errorMessage":"Measurement name cannot contain spaces","messagePattern":"Measurement name cannot contain spaces","errorType":"validation","errorClass":"InvalidMeasurementError","httpStatus":null,"severity":"error","filePath":"influxdb3_py_api/src/line_builder/line_builder.py","lineNumber":32,"sourceCode":"    pass\n\n\nclass InvalidKeyError(InfluxDBError):\n    \"\"\"Raised when a tag or field key is invalid\"\"\"\n\n    pass\n\n\nclass InvalidLineError(InfluxDBError):\n    \"\"\"Raised when a line protocol string is invalid\"\"\"\n\n    pass\n\n\nclass LineBuilder:\n    def __init__(self, measurement: str):\n        if \" \" in measurement:\n            raise InvalidMeasurementError(\"Measurement name cannot contain spaces\")\n        self.measurement = measurement\n        self.tags: OrderedDict[str, str] = OrderedDict()\n        self.fields: OrderedDict[str, str] = OrderedDict()\n        self._timestamp_ns: Optional[int] = None\n\n    def _validate_key(self, key: str, key_type: str) -> None:\n        \"\"\"Validate that a key does not contain spaces, commas, or equals signs.\"\"\"\n        if not key:\n            raise InvalidKeyError(f\"{key_type} key cannot be empty\")\n        if \" \" in key:\n            raise InvalidKeyError(f\"{key_type} key '{key}' cannot contain spaces\")\n        if \",\" in key:\n            raise InvalidKeyError(f\"{key_type} key '{key}' cannot contain commas\")\n        if \"=\" in key:\n            raise InvalidKeyError(f\"{key_type} key '{key}' cannot contain equals signs\")\n\n    def _escape_measurement(self, value: str) -> str:\n        \"\"\"Escape characters in measurement names according to line protocol.\"\"\"","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/influxdata/influxdb/blob/d28e26e048401c53cbb98cf2d6ab0cf1e98048ca/influxdb3_py_api/src/line_builder/line_builder.py#L14-L50","documentation":"LineBuilder.__init__ in the influxdb3_py_api Python package (the API used by InfluxDB 3 processing-engine plugins to build line protocol) rejects any measurement name containing a space. In line protocol a space separates the measurement+tag set from the field set, so an unescaped space makes the line ambiguous; the constructor fails fast with InvalidMeasurementError instead of emitting a corrupt line. Although build() later escapes commas and spaces via _escape_measurement, the constructor still rejects spaces upfront.","triggerScenarios":"Calling LineBuilder('cpu usage') or LineBuilder('my measurement') in Python plugin code, e.g. when constructing lines for context.write_db_lines() or a LogWriter. Any measurement string containing at least one space character raises immediately, before any tag or field can be added.","commonSituations":"Measurement names taken from user input, CSV headers, metric names imported from other monitoring systems (e.g. 'disk used percent'), or copy-pasted strings with stray whitespace. Plugins that build measurement names dynamically from unvalidated third-party data.","solutions":["Replace spaces in the measurement name with underscores or dashes before constructing LineBuilder","If the space is only leading/trailing whitespace, apply name.strip() first","For truly arbitrary names, sanitize at your ingest boundary (whitelist/replace) so builder input is always clean","Wrap construction in try/except InvalidMeasurementError and log the offending name when ingesting external data"],"exampleFix":"# before\nbuilder = LineBuilder(\"cpu usage\")  # InvalidMeasurementError\n\n# after\nbuilder = LineBuilder(\"cpu_usage\")","handlingStrategy":"validation","validationCode":"def safe_measurement(name: str) -> str:\n    cleaned = name.strip().replace(\" \", \"_\")\n    if not cleaned:\n        raise ValueError(\"measurement name is empty\")\n    return cleaned\n\nbuilder = LineBuilder(safe_measurement(raw_name))","typeGuard":null,"tryCatchPattern":"from influxdb3_py_api.line_builder import LineBuilder, InfluxDBError\n\ntry:\n    builder = LineBuilder(raw_name)\nexcept InfluxDBError as e:\n    logger.warning(\"skipping invalid measurement %r: %s\", raw_name, e)\n    return","preventionTips":["Normalize measurement names (strip whitespace, replace inner spaces) at the ingest boundary before they reach LineBuilder","Add unit tests that construct LineBuilder with your real-world measurement names","Never feed unvalidated third-party strings directly as identifiers"],"tags":["influxdb","line-protocol","python","measurement","validation"],"backgroundTag":"line-protocol-validation","analyzedSha":"d28e26e048401c53cbb98cf2d6ab0cf1e98048ca","analyzedAt":"2026-08-16T19:53:34.623Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}