{"id":"07d0fa549eee11bd","repo":"sqlalchemy/alembic","slug":"recreate-may-be-one-of-auto-always-or-never","errorCode":null,"errorMessage":"recreate may be one of 'auto', 'always', or 'never'.","messagePattern":"recreate may be one of 'auto', 'always', or 'never'\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"alembic/operations/batch.py","lineNumber":68,"sourceCode":"    def __init__(\n        self,\n        operations,\n        table_name,\n        schema,\n        recreate,\n        copy_from,\n        table_args,\n        table_kwargs,\n        reflect_args,\n        reflect_kwargs,\n        naming_convention,\n        partial_reordering,\n    ):\n        self.operations = operations\n        self.table_name = table_name\n        self.schema = schema\n        if recreate not in (\"auto\", \"always\", \"never\"):\n            raise ValueError(\n                \"recreate may be one of 'auto', 'always', or 'never'.\"\n            )\n        self.recreate = recreate\n        self.copy_from = copy_from\n        self.table_args = table_args\n        self.table_kwargs = dict(table_kwargs)\n        self.reflect_args = reflect_args\n        self.reflect_kwargs = dict(reflect_kwargs)\n        self.reflect_kwargs.setdefault(\n            \"listeners\", list(self.reflect_kwargs.get(\"listeners\", ()))\n        )\n        self.reflect_kwargs[\"listeners\"].append(\n            (\"column_reflect\", operations.impl.autogen_column_reflect)\n        )\n        self.naming_convention = naming_convention\n        self.partial_reordering = partial_reordering\n        self.batch = []\n","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/sqlalchemy/alembic/blob/44fb3450330204b222ff05135e1fbbbdb28c44db/alembic/operations/batch.py#L50-L86","documentation":"BatchOperationsImpl.__init__ validates the recreate argument against the fixed set {'auto','always','never'} because these three encode distinct table-rebuild strategies: auto lets the dialect decide, always forces a copy-and-move rebuild, never forbids it. Any other value is a configuration typo that would silently fall through to never.","triggerScenarios":"Passing recreate= to batch_alter_table with a value like 'yes', 'true', 'false', True (bool), None, or a misspelled string.","commonSituations":"A boolean passed instead of a string (recreate=True); a string copied from a tutorial that used a non-standard token; a config-driven value that wasn't validated upstream.","solutions":["Use recreate='auto' (default) to let the dialect decide based on the operation mix.","Use recreate='always' to force a full table rebuild (e.g. for SQLite constraint changes).","Use recreate='never' to forbid rebuild (will error if the operation requires it)."],"exampleFix":"// before\nwith op.batch_alter_table('t', recreate=True) as batch_op:  # bool -> ValueError\n    ...\n// after\nwith op.batch_alter_table('t', recreate='always') as batch_op:\n    ...","handlingStrategy":"validation","validationCode":"if recreate not in (\"auto\", \"always\", \"never\"):\n    raise ValueError(\"recreate must be one of 'auto','always','never'\")","typeGuard":"def is_valid_recreate(v) -> bool:\n    return v in (\"auto\", \"always\", \"never\")","tryCatchPattern":null,"preventionTips":["Pass string literals, not booleans, to recreate.","Default to recreate='auto' unless you have a specific reason.","Validate config-driven recreate values before passing them in."],"tags":["batch-mode","configuration","validation"],"analyzedSha":"44fb3450330204b222ff05135e1fbbbdb28c44db","analyzedAt":"2026-08-04T19:57:10.248Z","schemaVersion":2}