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
During incremental table sync, column-level actions are keyed by sub-keys that must be prefixed with `_COL_SUBKEY_PREFIX` (identifying them as column actions). `_apply_column_actions` raises `ValueError` when it encounters a sub-key with an unexpected format, protecting against internal state mismatches or hand-crafted table actions.
Source
Thrown at python/cocoindex/connectors/sqlite/_target.py:811
def _apply_column_actions(
conn: sqlite3.Connection,
table_name: str,
schema: TableSchema[Any],
column_actions: dict[str, statediff.DiffAction],
) -> None:
"""Apply column-level changes to the table.
Note: SQLite has limited ALTER TABLE support. Adding columns is supported,
but modifying or dropping columns requires recreating the table (in older SQLite).
SQLite 3.35.0+ supports DROP COLUMN.
"""
qualified_name = _qualified_table_name(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) :]
# Defensive: we never ALTER PK columns here.
if col_name in pk_cols:
continue
if action == "delete":
# SQLite 3.35.0+ supports DROP COLUMN
try:
conn.execute(f'ALTER TABLE {qualified_name} DROP COLUMN "{col_name}"')
except sqlite3.OperationalError:
# Older SQLite doesn't support DROP COLUMN - silently skip
pass
continue
desired_col = non_pk_col_by_name.get(col_name)View on GitHub (pinned to e84aa99b32)
Solutions
- This indicates an internal invariant violation — report it with the failing action keys and cocoindex version
- Re-sync the affected table from scratch (drop the state so actions are regenerated by the current version)
- If writing custom connector code, prefix column sub-keys with the library's `_COL_SUBKEY_PREFIX` constant rather than raw names
Defensive patterns
Strategy: try-catch
Try / catch
try:
await app.update()
except ValueError as e:
if "Unexpected column subkey format" in str(e):
report_bug_with_version() # internal invariant violation
raise Prevention
- Do not construct or mutate table action dicts manually
- Avoid mixing cocoindex versions against the same database state; re-sync after upgrades
- Pin the cocoindex version used to write and read persisted state
When it happens
Trigger: An internal bug or stale stored state produces column action keys without the expected prefix; users manually constructing or tampering with table action dictionaries passed into the apply path.
Common situations: Upgrading cocoindex across versions where persisted action/plan formats changed; custom connector code that builds its own action dict with bare column names instead of prefixed sub-keys.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Failed to add column {col_name!r} to SQLite table {table_nam
- Failed to replace column {col_name!r} in SQLite table {table
- Unexpected column subkey format: {sub_key!r}, expected to st
- Unexpected column subkey format: {sub_key!r}, expected to st
- Unexpected schema type: {type(resolved_schema)}
AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08).
Data as JSON: /api/errors/9e4d1e18481bce8d.
Report an issue: GitHub.