cocoindex-io/cocoindex · error · ValueError
Unsupported LanceDB column action for in-place evolution: {a
Error message
Unsupported LanceDB column action for in-place evolution: {action!r} What it means
During LanceDB target schema reconciliation, _apply_column_actions only supports additive in-place schema evolution ('insert'/'upsert' actions, which add new nullable columns backfilled with null). Any other DiffAction (e.g. delete, update) for a column subkey means the desired change cannot be applied in place, so the library raises rather than corrupting the table. Dropping or altering columns requires recreating the table instead.
Source
Thrown at python/cocoindex/connectors/lancedb/_target.py:1160
continue
if col_name in existing_cols:
continue
desired_col = schema.columns.get(col_name)
if desired_col is None:
continue
if action in ("insert", "upsert"):
fields_to_add.append(
# Existing rows are backfilled with null, so additive schema
# evolution must materialize the new column as nullable.
pa.field(col_name, desired_col.type, nullable=True)
)
if desired_col.nullable:
null_backfilled_columns.add(col_name)
continue
raise ValueError(
f"Unsupported LanceDB column action for in-place evolution: {action!r}"
)
if fields_to_add:
await table.add_columns(fields_to_add)
return frozenset(null_backfilled_columns)
return frozenset()
def reconcile(
self,
key: coco.StableKey,
desired_state: _TableSpec | coco.NonExistenceType,
prev_possible_records: Collection[_TableTrackingRecord],
prev_may_be_missing: bool,
/,
) -> (
coco.TargetReconcileOutput[_TableAction, _TableTrackingRecord, _RowHandler]
| NoneView on GitHub (pinned to e84aa99b32)
Solutions
- Drop the existing LanceDB table (or point the target at a new table name) so it is recreated from the current declared schema
- Restore the removed/changed column in the declared schema so the diff is only additive
- Do a two-phase migration: add the new column (supported additive op), backfill, then manually remove the old column via LanceDB tooling
- Inspect the diff actions by comparing schema.columns with the live table schema to identify the offending column
Example fix
// before
class Row(NamedTuple):
id: str
text: str
legacy_col: str # removed later -> 'delete' action -> error
// after
class Row(NamedTuple):
id: str
text: str
# and recreate the table (or use a fresh table name) since column drops are not in-place Defensive patterns
Strategy: validation
Validate before calling
live_cols = set((await table.schema()).names)
declared = set(schema.columns)
if not (declared >= live_cols and live_cols <= declared | set()):
# non-additive diff possible: drops or type changes
if live_cols - declared:
raise RuntimeError(f"columns removed; recreate table: {live_cols - declared}") Type guard
def is_additive(actions: dict[str, str]) -> bool:
return all(a in ("insert", "upsert") for a in actions.values()) Try / catch
try:
await app.update()
except ValueError as e:
if "Unsupported LanceDB column action" in str(e):
logger.warning("non-additive schema change; recreating table: %s", e)
await drop_lancedb_table(table_name)
await app.update()
else:
raise Prevention
- Treat declared column removals/renames as breaking changes: bump the table name or migrate explicitly
- Prefer adding new columns and deprecating old ones over in-place type changes
- Run schema diff checks in CI before deploying pipeline changes
- Keep a version suffix in table names for destructive schema migrations
When it happens
Trigger: A diff between the declared table schema and the existing LanceDB table produces a non-additive column action (delete/update/replace) in column_actions, e.g. a column was removed or its type changed in the declared TableSpec while the table already exists.
Common situations: Removing or renaming a field in a row dataclass after a table already has data; changing a column's type; changing a column to/from primary key in ways the additive path skips; running an updated pipeline version against an old LanceDB table.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Partial reads are not supported for Google Drive files.
- lancedb and pyarrow are required to use the LanceDB connecto
- VectorSchemaProvider is required for NumPy ndarray type.
- Invalid vector dimension: {vector_schema.size}
- VectorSchemaProvider is only supported for NumPy ndarray typ
AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08).
Data as JSON: /api/errors/0b5a022ca1199c8e.
Report an issue: GitHub.