{"id":"9fb6dc0126d9ed87","repo":"sequelize/sequelize","slug":"abstract-is-not-a-valid-option-for-table-did-y","errorCode":null,"errorMessage":"`abstract` is not a valid option for @Table. Did you mean to use @Table.Abstract?","messagePattern":"`abstract` is not a valid option for @Table\\. Did you mean to use @Table\\.Abstract\\?","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/decorators/legacy/table.ts","lineNumber":33,"sourceCode":" * class User extends Model<InferAttributes<User>, InferCreationAttributes<User>> {}\n * ```\n *\n * @param options\n */\nexport function Table<M extends Model = Model>(options: ModelOptions<M>): ClassDecorator;\nexport function Table(target: ModelStatic): void;\nexport function Table(arg: any): undefined | ClassDecorator {\n  if (typeof arg === 'function') {\n    annotate(arg);\n\n    return undefined;\n  }\n\n  const options: ModelOptions = { ...arg };\n\n  // @ts-expect-error -- making sure the option is not provided.\n  if (options.abstract) {\n    throw new Error(\n      '`abstract` is not a valid option for @Table. Did you mean to use @Table.Abstract?',\n    );\n  }\n\n  return (target: any) => annotate(target, options);\n}\n\nfunction AbstractTable<M extends Model = Model>(\n  options: Omit<ModelOptions<M>, 'tableName' | 'name'>,\n): ClassDecorator;\nfunction AbstractTable(target: ModelStatic): void;\nfunction AbstractTable(arg: any): undefined | ClassDecorator {\n  if (typeof arg === 'function') {\n    annotate(arg, { abstract: true });\n\n    return undefined;\n  }\n","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/sequelize/sequelize/blob/7e1deec499d5afbb8d1877c2f4d545cead1214ec/packages/core/src/decorators/legacy/table.ts#L15-L51","documentation":"Thrown by the @Table decorator factory when the options object contains an `abstract: true` flag. Sequelize separates concrete and abstract table decorators: @Table is for real models and @Table.Abstract is for base-only models. Passing abstract inside @Table is rejected because the two code paths differ (abstract models are not registered with a sequelize instance and cannot be queried).","triggerScenarios":"Calling `@Table({ abstract: true })` or `@Table({ abstract: true, tableName: 'foo' })` on a class. Any truthy value under the `abstract` key inside the options passed to the plain @Table decorator triggers it.","commonSituations":"Coming from another ORM (TypeORM) where `@Entity({ abstract: true })` is the documented pattern. Copying a @Table call and adding abstract:true without reading the v7 docs. Migrating from v6 define-based abstract models.","solutions":["Use `@Table.Abstract(options)` instead of `@Table({ abstract: true, ... })`.","Remove the `abstract` key entirely if the model is meant to be concrete.","If you need an abstract base class with no options, use the bare `@Table.Abstract` form."],"exampleFix":"// before\n@Table({ abstract: true })\nabstract class Base extends Model {}\n\n// after\n@Table.Abstract()\nabstract class Base extends Model {}","handlingStrategy":"validation","validationCode":"// Validate @Table options do not include 'abstract'.\nfunction assertTableOptions(options: Record<string, unknown>) {\n  if ('abstract' in options && options.abstract) {\n    throw new Error('Use @Table.Abstract instead of @Table({ abstract: true })');\n  }\n}\nassertTableOptions(tableOpts);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat @Table and @Table.Abstract as two distinct APIs; never pass abstract to @Table.","Centralize model decorator selection in a factory to avoid the mistake.","Document the split in your project's model guidelines."],"tags":["decorators","table","abstract-models","configuration"],"analyzedSha":"7e1deec499d5afbb8d1877c2f4d545cead1214ec","analyzedAt":"2026-08-03T18:58:44.549Z","schemaVersion":2}