{"record":{"id":"5b6bf2b7292499cd","repo":"pathwaycom/pathway","slug":"the-mqtt-topic-to-publish-to-must-not-contain-the","errorCode":null,"errorMessage":"The MQTT topic to publish to must not contain the wildcard characters '+' or '#' (got {topic!r}); wildcards are only allowed when reading (subscribing).","messagePattern":"The MQTT topic to publish to must not contain the wildcard characters '\\+' or '#' \\(got (.+?)\\); wildcards are only allowed when reading \\(subscribing\\)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/pathway/io/mqtt/__init__.py","lineNumber":333,"sourceCode":"    ...     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,\n        topic=topic if isinstance(topic, str) else None,\n        topic_name_index=output_format.topic_name_index,","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/pathwaycom/pathway/blob/fa2f74a4649b7c5908690cf60137263d8d80de5f/python/pathway/io/mqtt/__init__.py#L315-L351","documentation":"In MQTT, '+' and '#' are subscription wildcards — a client cannot publish to them. pw.io.mqtt.write therefore rejects a string topic containing '+' or '#' with a ValueError echoing the offending topic and clarifying that wildcards are only valid on the read (subscribe) side.","triggerScenarios":"Reusing a subscription-style filter as the publish topic: pw.io.mqtt.write(table, uri, topic='sensors/+/temperature') or a shared TOPIC constant used by both read and write calls.","commonSituations":"One config value (e.g. MQTT_TOPIC='devices/#') shared between a reader and writer; copy-pasting an example subscribe filter into a publish call; dynamic topic columns mistakenly passed as strings.","solutions":["Publish to a concrete topic without wildcards: topic='sensors/kitchen/temperature'","Use separate config keys for read filters and write topics","For per-row topics, pass a column: topic=table.room (ColumnReference is not checked for wildcards as it is data-driven)"],"exampleFix":"# before\nTOPIC = \"sensors/+/temperature\"  # wildcard shared with reader\npw.io.mqtt.write(t, \"mqtt://localhost:1883\", topic=TOPIC)\n\n# after\nWRITE_TOPIC = \"sensors/kitchen/temperature\"\npw.io.mqtt.write(t, \"mqtt://localhost:1883\", topic=WRITE_TOPIC)","handlingStrategy":"type-guard","validationCode":"if isinstance(topic, str) and any(w in topic for w in \"+#\"):\n    raise ValueError(f\"{topic!r} contains publish-illegal wildcards; use a concrete topic\")","typeGuard":"def is_publishable_topic(topic) -> bool:\n    if isinstance(topic, pw.ColumnReference):\n        return True\n    return isinstance(topic, str) and topic != \"\" and not any(w in topic for w in \"+#\")","tryCatchPattern":"try:\n    pw.io.mqtt.write(table, uri, topic=topic)\nexcept ValueError as e:\n    if \"wildcard characters\" in str(e):\n        raise ValueError(\"Publish topics cannot use +/#; those are subscribe-only filters\") from e\n    raise","preventionTips":["Never reuse a subscription filter string as a publish topic","Guard string topics with a check for '+'/'#' in shared config loaders","Use ColumnReference topics when routing depends on row data"],"tags":["mqtt","pathway","topic","wildcard","validation"],"backgroundTag":null,"analyzedSha":"fa2f74a4649b7c5908690cf60137263d8d80de5f","analyzedAt":"2026-08-15T01:48:17.006Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}