{"record":{"id":"5895d61068599b59","repo":"pathwaycom/pathway","slug":"trying-to-modify-a-row-in-type-self-but-deletio","errorCode":null,"errorMessage":"Trying to modify a row in {type(self)} but deletions_enabled is set to False.","messagePattern":"Trying to modify a row in (.+?) but deletions_enabled is set to False\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/pathway/io/python/__init__.py","lineNumber":272,"sourceCode":"    ) -> dict[str, Any]:\n        match self._pw_format:\n            case \"json\":\n                values = json.loads(message.decode(encoding=\"utf-8\"))\n            case \"raw\":\n                values = {\"data\": message.decode(encoding=\"utf-8\")}\n            case _:\n                assert self._pw_format == \"binary\"\n                values = {\"data\": message}\n        if metadata is not None:\n            values[\"_metadata\"] = json.loads(metadata.decode(encoding=\"utf-8\"))\n        return values\n\n    def _add_inner(self, key: Pointer | None, values: dict[str, Any]) -> None:\n        if self._session_type == SessionType.NATIVE:\n            self._buffer.put((PythonConnectorEventType.INSERT, key, values))\n        elif self._session_type == SessionType.UPSERT:\n            if not self._deletions_enabled:\n                raise ValueError(\n                    f\"Trying to modify a row in {type(self)} but deletions_enabled is set to False.\"\n                )\n            self._buffer.put((PythonConnectorEventType.INSERT, key, values))\n        else:\n            raise NotImplementedError(f\"session type {self._session_type} not handled\")\n\n    def _remove(\n        self, key: Pointer, message: bytes, metadata: bytes | None = None\n    ) -> None:\n        self._remove_inner(key, self._get_values_dict(message, metadata))\n\n    def _remove_inner(self, key: Pointer | None, values: dict[str, Any]) -> None:\n        if not self._deletions_enabled:\n            raise ValueError(\n                f\"Trying to delete a row in {type(self)} but deletions_enabled is set to False.\"\n            )\n        self._buffer.put((PythonConnectorEventType.DELETE, key, values))\n","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/pathwaycom/pathway/blob/fa2f74a4649b7c5908690cf60137263d8d80de5f/python/pathway/io/python/__init__.py#L254-L290","documentation":"Raised by Pathway's Python input connector when a custom ConnectorSubject emits a modification (an upsert of an existing key) through a session of SessionType.UPSERT while deletions_enabled=False was passed to pw.io.python.read. With deletions disabled the engine assumes an append-only stream, so an upsert-style rewrite of a key is a contract violation and is rejected instead of silently dropping or corrupting state.","triggerScenarios":"Implementing a ConnectorSubject whose run() calls subject.next(key, values) twice with the same key (the second call is a modify) while the connector was created with pw.io.python.read(subject, ..., deletions_enabled=False); or commit/replay logic that re-emits rows.","commonSituations":"Feeding an upsert source (e.g. a dict-backed feed or Kafka compacted topic) into a pipeline configured for append-only processing to save memory; porting an existing subject from UPSERT semantics to static mode and forgetting duplicate keys can occur.","solutions":["Set deletions_enabled=True (default) in pw.io.python.read so updates to an existing key are legal.","Or make the subject truly append-only: never reuse a key in next(); derive unique keys per event (e.g. include a sequence number or timestamp).","If only late corrections arrive, emit the correction as a new row with a new key and dedupe downstream with reducers instead of mutating the key."],"exampleFix":"# before\ndef run(self):\n    self.next(\"row-1\", {\"v\": 1})\n    self.next(\"row-1\", {\"v\": 2})  # modification of existing key\npw.io.python.read(Subj(), schema=S, deletions_enabled=False)\n\n# after\npw.io.python.read(Subj(), schema=S)  # deletions_enabled=True allows upserts","handlingStrategy":"validation","validationCode":"may_update_keys = True  # set to False only for truly append-only sources\npw.io.python.read(Subj(), schema=S, deletions_enabled=may_update_keys)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set deletions_enabled=True whenever the source can emit the same key twice.","Derive unique keys per event if you intend an append-only connector.","Document the subject's key policy in its docstring so callers pick the right flag."],"tags":["pathway","python-connector","upsert","runtime","api-misuse"],"backgroundTag":null,"analyzedSha":"fa2f74a4649b7c5908690cf60137263d8d80de5f","analyzedAt":"2026-08-15T01:48:17.006Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}