pathwaycom/pathway · error · TypeError

SchemaRegistrySettings.urls must be a list of strings, got {

Error message

SchemaRegistrySettings.urls must be a list of strings, got {type(self.urls).__name__}. Wrap a single URL in a list: urls=['http://...'].

What it means

pw.io.deltalake.write accepts partition_columns as ColumnReference objects and verifies each one belongs to the table being written before converting to column names; partitioning is table-scoped so a foreign reference is invalid.

Source

Thrown at python/pathway/internals/_io_helpers.py:274

        headers: Additional headers to include in HTTP requests to the schema registry.
        proxy: Proxy address for registry requests.
        timeout: Timeout duration for network requests, in seconds.

    Returns:
        The configuration object.
    """

    urls: list[str]
    token_authorization: str | None = None
    username: str | None = None
    password: str | None = None
    headers: list[SchemaRegistryHeader] | None = None
    proxy: str | None = None
    timeout: datetime.timedelta | None = None

    def __post_init__(self):
        if not isinstance(self.urls, (list, tuple)):
            raise TypeError(
                f"SchemaRegistrySettings.urls must be a list of strings, "
                f"got {type(self.urls).__name__}. Wrap a single URL in a "
                f"list: urls=['http://...']."
            )
        if not self.urls:
            raise ValueError(
                "SchemaRegistrySettings requires at least one entry in 'urls'; "
                "got an empty list."
            )
        for i, url in enumerate(self.urls):
            if not isinstance(url, str) or not url:
                raise ValueError(
                    f"SchemaRegistrySettings.urls[{i}] must be a non-empty "
                    f"string; got {url!r}."
                )
        for field_name in ("token_authorization", "username", "password", "proxy"):
            value = getattr(self, field_name)
            if value is not None and not isinstance(value, str):

View on GitHub (pinned to fa2f74a464)

Solutions

  1. Reference columns from the table being written: partition_columns=[t.event_date].
  2. If the partition key must be computed, add it to the table first (with_columns) and pass the new column.

Example fix

# before
enriched = raw.with_columns(day=pw.this.ts.dt())
pw.io.deltalake.write(enriched, uri, partition_columns=[raw.day])

# after
enriched = raw.with_columns(day=pw.this.ts.dt())
pw.io.deltalake.write(enriched, uri, partition_columns=[enriched.day])
Defensive patterns

Strategy: validation

Validate before calling

for c in partition_columns or []:
    assert c._table is table, f"partition column {c._name!r} not from target table"
pw.io.deltalake.write(table, uri, partition_columns=partition_columns)

Type guard

def columns_from_table(columns: list, table: pw.Table) -> bool:
    return all(c._table is table for c in columns)

Prevention

When it happens

Trigger: Passing partition_columns=[other_table.event_date] where other_table is not the table argument of pw.io.deltalake.write.

Common situations: Pipeline transforms a table (t = raw.with_columns(...)) but partition_columns still references the original raw table's column; multiple derived tables make it easy to grab the wrong reference.

Related errors


AI-assisted analysis of pathwaycom/pathway@fa2f74a464 (2026-08-15). Data as JSON: /api/errors/1134a1366b61f784. Report an issue: GitHub.