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
- Use the connector's own action-building helpers so sub-keys are created with _COL_SUBKEY_PREFIX instead of constructing them manually.
- Prefix the raw column name with _COL_SUBKEY_PREFIX if you build column actions yourself.
- 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
- Never construct column action dicts by hand; use the connector's own helpers.
- Keep the cocoindex package version consistent across environments.
- Add a startup smoke test that performs a tiny sync against a temp table.
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
- row_count must be positive
- change fingerprint {fp} is present in a cached memo entry bu
- Primary key column '{pk}' not found in columns: {list(self.c
- record_type must be a record type (dataclass, NamedTuple, Py
- Invalid Snowflake {kind}: {name!r}
AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08).
Data as JSON: /api/errors/2911e7232fc44078.
Report an issue: GitHub.