{"record":{"id":"1ab7bd74de808422","repo":"pathwaycom/pathway","slug":"at-least-two-columns-must-participate-in-a-connect","errorCode":null,"errorMessage":"At least two columns must participate in a connector group","messagePattern":"At least two columns must participate in a connector group","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/pathway/io/_synchronization.py","lineNumber":234,"sourceCode":"    **Example scenario:**\n    Consider a synchronization group with two data sources, both tracking a ``timestamp``\n    column, and ``max_difference`` set to 600 seconds (10 minutes).\n\n    - Initially, both sources send a record with timestamp ``T``.\n    - Later, the first source sends a record with ``T + 1h``. \\\n      This record is not yet forwarded for processing because it exceeds ``max_difference``.\n    - If the second source then sends a record with ``T + 1h``, the system detects a 1-hour gap. \\\n      Since both sources have moved beyond ``T``, the synchronization group accepts ``T + 1h`` \\\n      as the new baseline and continues processing from there.\n    - However, if the second source instead sends a record with ``T + 5m``, this record \\\n      is processed normally. The system will continue waiting for the first source to \\\n      catch up before advancing further.\n\n    This behavior ensures that data gaps do not cause deadlocks but are properly detected and handled.\n    \"\"\"\n\n    if len(columns) < 2:\n        raise ValueError(\"At least two columns must participate in a connector group\")\n\n    if not isinstance(max_difference, int) and not isinstance(\n        max_difference, datetime.timedelta\n    ):\n        raise ValueError(\n            \"The 'max_difference' must either be an integer or a datetime.timedelta\"\n        )\n\n    if isinstance(max_difference, int) and max_difference < 0:\n        raise ValueError(\"The 'max_difference' can't be negative\")\n    if isinstance(\n        max_difference, datetime.timedelta\n    ) and max_difference < datetime.timedelta(0):\n        raise ValueError(\"The 'max_difference' can't be negative\")\n\n    column_types = set()\n    for synchronized_column in columns:\n        if isinstance(synchronized_column, ColumnReference):","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/pathwaycom/pathway/blob/fa2f74a4649b7c5908690cf60137263d8d80de5f/python/pathway/io/_synchronization.py#L216-L252","documentation":"ValueError raised by the connector synchronization API (pathway.io.synchronize / the sync() function in _synchronization.py) when fewer than two columns are passed. A synchronization group by definition coordinates at least two data sources, so a single column is rejected.","triggerScenarios":"Calling the sync/synchronize API with a single column: sync(transactions.time, max_difference=600); passing an empty columns list; passing one ColumnReference where two SynchronizedColumn entries were intended.","commonSituations":"Adding a second source incrementally and testing with one first; refactoring that drops a column argument; misunderstanding that synchronization coordinates sources against each other, not against wall-clock time.","solutions":["Provide at least two columns from at least two different input tables: sync(t1.time, t2.time, max_difference=600)","If you only have one source, remove the synchronization group entirely","Wrap bare columns in pw.io.SynchronizedColumn when you also need priority/idle_duration, keeping at least two entries"],"exampleFix":"// before\npw.io.synchronize(transactions.time, max_difference=600)\n\n// after\npw.io.synchronize(transactions.time, login_events.time, max_difference=600)","handlingStrategy":"validation","validationCode":"def validate_sync_columns(columns) -> None:\n    if len(columns) < 2:\n        raise ValueError('synchronization group needs >= 2 columns from different tables')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Model synchronization as multi-source by construction; require >= 2 columns in wrappers","Wrap the sync API in project-level helpers that validate arguments","Skip the sync call when only one source is configured"],"tags":["pathway","io","synchronization","connectors"],"backgroundTag":null,"analyzedSha":"fa2f74a4649b7c5908690cf60137263d8d80de5f","analyzedAt":"2026-08-15T01:48:17.006Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}