pathwaycom/pathway · error · ValueError

{arg_name} must not contain NUL characters

Error message

{arg_name} must not contain NUL characters

What it means

This ValueError is raised by Pathway's MSSQL connector when table_name or schema_name contains a NUL character ("\0"). Embedded NUL bytes corrupt the TDS wire stream that the SQL Server driver uses, producing garbled protocol errors at runtime that are very hard to trace back to the argument. The up-front check converts that into a clear call-time error.

Source

Thrown at python/pathway/io/mssql/__init__.py:33

from pathway.internals.trace import trace_user_frame
from pathway.io._utils import (
    SNAPSHOT_OUTPUT_TABLE_TYPE,
    get_column_index,
    init_mode_from_str,
    read_schema,
)


def _validate_identifier(arg_name: str, value: str) -> None:
    """Reject empty / NUL-containing identifiers up-front so users see a
    clear ``ValueError`` at call time instead of an opaque SQL Server parse
    error (`[]` is not a legal bracket-quoted identifier; embedded NUL
    bytes corrupt the TDS stream).
    """
    if value == "":
        raise ValueError(f"{arg_name} must not be empty")
    if "\0" in value:
        raise ValueError(f"{arg_name} must not contain NUL characters")


@check_arg_types
@trace_user_frame
def read(
    connection_string: str,
    table_name: str,
    schema: type[Schema],
    *,
    mode: Literal["static", "streaming"] = "streaming",
    schema_name: str = "dbo",
    autocommit_duration_ms: int | None = 1500,
    name: str | None = None,
    max_backlog_size: int | None = None,
    debug_data: Any = None,
) -> Table:
    """Reads a table from a Microsoft SQL Server database.

View on GitHub (pinned to fa2f74a464)

Solutions

  1. Strip or reject NUL characters before the call: name = name.replace("\0", "") only if stripping is semantically safe, otherwise fix the upstream decoding.
  2. If the name comes from a binary/fixed-width source, decode and cut at the first NUL: name = raw.split(b"\0", 1)[0].decode().
  3. Log the repr() of the identifier when building it so NULs are visible during debugging.

Example fix

# before
table_name = raw_record[:64].decode()  # may contain trailing \x00
pw.io.mssql.read(conn_str, table_name, schema=MySchema)

# after
table_name = raw_record[:64].split(b"\0", 1)[0].decode()
pw.io.mssql.read(conn_str, table_name, schema=MySchema)
Defensive patterns

Strategy: validation

Validate before calling

def clean_identifier(value: str) -> str:
    if "\0" in value:
        raise RuntimeError(f"identifier {value!r} contains NUL bytes")
    return value

table_name = clean_identifier(table_name)

Type guard

def is_nul_free(value: str) -> bool:
    return isinstance(value, str) and "\0" not in value

Try / catch

try:
    pw.io.mssql.read(conn, table_name, schema=MySchema)
except ValueError as e:
    if "NUL" in str(e):
        table_name = table_name.replace("\0", "")
        # retry only if stripping is semantically safe for your data
    raise

Prevention

When it happens

Trigger: Passing a table_name or schema_name that contains "\0" to pw.io.mssql.read/write; common when the name is decoded from binary data, read from a file without stripping trailing NULs, or built from a buffer slice that includes padding.

Common situations: Names sourced from fixed-width binary records or NUL-padded C strings; data read with encoding errors that leave \x00 characters; concatenating strings from byte-oriented APIs without decoding properly.

Related errors


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