cocoindex-io/cocoindex · error · ValueError

Unexpected column subkey format: {sub_key!r}, expected to st

Error message

Unexpected column subkey format: {sub_key!r}, expected to start with {_COL_SUBKEY_PREFIX!r}

What it means

Column-level actions are keyed by sub-keys that must carry the reserved `_COL_SUBKEY_PREFIX` so `_apply_column_actions` can strip the prefix to recover the column name. A sub-key without the prefix means the action key format is not what the connector produced — an internal invariant violation — so it raises immediately rather than misinterpreting the key.

Source

Thrown at python/cocoindex/connectors/snowflake/_target.py:598

    if_not_exists_sql = " IF NOT EXISTS" if if_not_exists else ""
    qualified_name = _qualified_table_name(key.database, key.schema, key.table_name)
    columns_sql = ", ".join(col_defs)
    cursor.execute(f"CREATE TABLE{if_not_exists_sql} {qualified_name} ({columns_sql})")


def _apply_column_actions(
    cursor: Any,
    key: _TableKey,
    schema: TableSchema[Any],
    column_actions: dict[str, statediff.DiffAction],
) -> None:
    qualified_name = _qualified_table_name(key.database, key.schema, key.table_name)
    pk_cols = set(schema.primary_key)
    non_pk_col_by_name = {n: c for n, c in schema.columns.items() if n not in pk_cols}

    for sub_key, action in column_actions.items():
        if not sub_key.startswith(_COL_SUBKEY_PREFIX):
            raise ValueError(
                f"Unexpected column subkey format: {sub_key!r}, expected to start with {_COL_SUBKEY_PREFIX!r}"
            )
        col_name = sub_key[len(_COL_SUBKEY_PREFIX) :]
        if col_name in pk_cols:
            continue

        if action == "delete":
            cursor.execute(
                f'ALTER TABLE {qualified_name} DROP COLUMN IF EXISTS "{col_name}"'
            )
            continue

        desired_col = non_pk_col_by_name.get(col_name)
        if desired_col is None:
            continue

        if action == "insert":
            cursor.execute(

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Use the connector's own action-building helpers so sub-keys are created with _COL_SUBKEY_PREFIX instead of constructing them manually.
  2. Prefix the raw column name with _COL_SUBKEY_PREFIX if you build column actions yourself.
  3. Align package versions if a custom fork emits the old sub-key format; report upstream if triggered by stock code.

Example fix

// before
column_actions[row["colname"]] = action
// after
column_actions[_COL_SUBKEY_PREFIX + row["colname"]] = action
Defensive patterns

Strategy: validation

Validate before calling

bad = [k for k in column_actions if not k.startswith(_COL_SUBKEY_PREFIX)]
if bad:
    raise ValueError(f"Column action keys missing prefix: {bad}")

Try / catch

try:
    apply_actions(...)
except ValueError as e:
    if "Unexpected column subkey format" in str(e):
        logging.error("Stale/custom action key format: %s", e)
        raise
    raise

Prevention

When it happens

Trigger: `_apply_actions` receives a column_actions dict containing a key that doesn't start with the internal prefix, e.g. a raw column name passed instead of the prefixed sub-key — normally only possible when custom/patched code constructs the actions dict.

Common situations: Hand-rolled or monkey-patched action generation, version mismatch between a custom handler that builds sub-keys and the current connector format.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08). Data as JSON: /api/errors/2911e7232fc44078. Report an issue: GitHub.