{"record":{"id":"af34fdf2f9ed660d","repo":"cocoindex-io/cocoindex","slug":"failed-to-replace-column-col-name-r-in-sqlite-ta","errorCode":null,"errorMessage":"Failed to replace column {col_name!r} in SQLite table {table_name!r}: {e}","messagePattern":"Failed to replace column (.+?) in SQLite table (.+?): (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/connectors/sqlite/_target.py","lineNumber":870,"sourceCode":"\n        if action == \"replace\":\n            # SQLite doesn't support ALTER COLUMN TYPE directly.\n            # For type changes, attempt to drop and re-add column.\n            try:\n                conn.execute(f'ALTER TABLE {qualified_name} DROP COLUMN \"{col_name}\"')\n            except sqlite3.OperationalError:\n                pass\n            nullable = \"\" if desired_col.nullable else \" NOT NULL\"\n            try:\n                conn.execute(\n                    f\"ALTER TABLE {qualified_name} \"\n                    f'ADD COLUMN \"{col_name}\" {desired_col.type}{nullable}'\n                )\n            except sqlite3.OperationalError as e:\n                if \"duplicate column name\" in str(e).lower():\n                    pass\n                else:\n                    raise RuntimeError(\n                        f\"Failed to replace column {col_name!r} in SQLite table {table_name!r}: {e}\"\n                    ) from e\n            continue\n\n\ndef _apply_table_actions(\n    context_provider: ContextProvider,\n    actions: Sequence[_TableAction],\n) -> list[coco.ChildTargetDef[\"_RowHandler\"] | None]:\n    \"\"\"Apply table actions (DDL) and return child row handlers.\"\"\"\n    actions_list = list(actions)\n    outputs: list[coco.ChildTargetDef[_RowHandler] | None] = [None] * len(actions_list)\n\n    # Group actions by table key so we can apply all DDL for the same table\n    by_key: dict[_TableKey, list[int]] = {}\n    for i, action in enumerate(actions_list):\n        by_key.setdefault(action.key, []).append(i)\n","sourceCodeStart":852,"sourceCodeEnd":888,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/connectors/sqlite/_target.py#L852-L888","documentation":"For a `replace` column action, SQLite has no `ALTER COLUMN TYPE`, so the connector emulates replacement by adding a new column with the desired type (after copying data). If that `ALTER TABLE ... ADD COLUMN` fails with anything other than 'duplicate column name', the `OperationalError` is wrapped in a `RuntimeError` naming the column and table.","triggerScenarios":"Replacing a column with a type SQLite cannot add (invalid type string, bad vector spec); a non-nullable add violating SQLite ADD COLUMN rules; the target table having been dropped or locked by another connection mid-migration.","commonSituations":"Changing a column's type in a record dataclass (e.g. `int` to a vector) triggers column replacement during sync; running the app against a database file opened by another process holding a write lock.","solutions":["Inspect the wrapped SQLite error message for the exact ADD COLUMN failure","Fix the changed field's type mapping so it compiles to a valid SQLite type","Make the replacement column nullable or give it a default value","Close other connections / retry the sync once the database is not locked"],"exampleFix":"// before\nclass Row:\n    tags: int  # changed from str, triggers replace\n// after — revert the type, or delete/recreate the table to avoid in-place replace\nclass Row:\n    tags: str","handlingStrategy":"try-catch","validationCode":"# detect type changes on pk-adjacent/replaceable columns before syncing\nassert all(isinstance(f.type, type) for f in dataclasses.fields(MyRow))","typeGuard":null,"tryCatchPattern":"try:\n    await app.update()\nexcept RuntimeError as e:\n    if str(e).startswith(\"Failed to replace column\"):\n        inspect(e.__cause__)  # underlying OperationalError has the real reason\n    else:\n        raise","preventionTips":["Treat column type changes as migrations: prefer dropping/recreating the table","Verify the replacement type compiles to a valid SQLite type","Release other connections/locks before running schema-changing syncs"],"tags":["sqlite","alter-table","schema-migration","sql"],"backgroundTag":"database-write-failed","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}