{"record":{"id":"658627b544182a87","repo":"pathwaycom/pathway","slug":"the-mqtt-topic-to-publish-to-must-not-be-empty","errorCode":null,"errorMessage":"The MQTT topic to publish to must not be empty.","messagePattern":"The MQTT topic to publish to must not be empty\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/pathway/io/mqtt/__init__.py","lineNumber":331,"sourceCode":"    ...     \"mqtt://localhost:1883/?client_id=test\",\n    ...     topic=\"test/topic\",\n    ...     format=\"plaintext\",\n    ...     value=table.owner,\n    ... )\n\n    Finally, if you'd like the topic to be dynamic and depend on the owner of the pet,\n    you can specify this column definition as the topic:\n\n    >>> pw.io.mqtt.write(\n    ...     table,\n    ...     \"mqtt://localhost:1883/?client_id=test\",\n    ...     topic=table.owner,\n    ...     format=\"json\",\n    ... )\n    \"\"\"\n    if isinstance(topic, str):\n        if topic == \"\":\n            raise ValueError(\"The MQTT topic to publish to must not be empty.\")\n        if \"+\" in topic or \"#\" in topic:\n            raise ValueError(\n                \"The MQTT topic to publish to must not contain the wildcard characters \"\n                f\"'+' or '#' (got {topic!r}); wildcards are only allowed when reading \"\n                \"(subscribing).\"\n            )\n    output_format = MessageQueueOutputFormat.construct(\n        table,\n        format=format,\n        delimiter=delimiter,\n        value=value,\n        topic_name=topic if isinstance(topic, ColumnReference) else None,\n    )\n    table = output_format.table\n\n    data_storage = api.DataStorage(\n        storage_type=\"mqtt\",\n        path=uri,","sourceCodeStart":313,"sourceCodeEnd":349,"githubUrl":"https://github.com/pathwaycom/pathway/blob/fa2f74a4649b7c5908690cf60137263d8d80de5f/python/pathway/io/mqtt/__init__.py#L313-L349","documentation":"pw.io.mqtt.write publishes to a single concrete topic (or a per-row column via a ColumnReference); unlike subscribing, publishing to an empty topic is invalid MQTT, so the connector raises this ValueError when the topic argument is an empty string.","triggerScenarios":"Calling pw.io.mqtt.write(table, uri, topic='') — typically a topic read from configuration that defaulted to or was set to the empty string.","commonSituations":"Env-driven topic configuration that is unset in one environment (e.g. works locally, empty in CI); template strings where a topic component is missing.","solutions":["Set a concrete topic name, e.g. topic='alerts/high'","For dynamic per-row topics, pass a ColumnReference instead: topic=table.owner","Validate config before pipeline construction: if not topic: raise ValueError(...)"],"exampleFix":"# before\npw.io.mqtt.write(t, \"mqtt://localhost:1883\", topic=\"\")\n\n# after\npw.io.mqtt.write(t, \"mqtt://localhost:1883\", topic=\"alerts/high\")","handlingStrategy":"validation","validationCode":"if isinstance(topic, str):\n    assert topic, \"MQTT publish topic must be non-empty\"\n# column-based topics are data-driven and exempt","typeGuard":"def is_valid_publish_topic(topic) -> bool:\n    if isinstance(topic, pw.ColumnReference):\n        return True  # per-row topic, validated by data\n    return isinstance(topic, str) and topic != \"\"","tryCatchPattern":null,"preventionTips":["Keep separate config values for read filters and write topics","Fail fast on empty strings from config at application startup","Prefer per-row ColumnReference topics for dynamic routing"],"tags":["mqtt","pathway","configuration","topic","validation"],"backgroundTag":null,"analyzedSha":"fa2f74a4649b7c5908690cf60137263d8d80de5f","analyzedAt":"2026-08-15T01:48:17.006Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}