{"id":"de829111e8b618c4","repo":"sequelize/sequelize","slug":"naming-collision-between-attribute-associationn","errorCode":null,"errorMessage":"Naming collision between attribute '${associationName}' and association '${associationName}' on model ${source.name}. To remedy this, change the \"as\" options in your association definition","messagePattern":"Naming collision between attribute '(.+?)' and association '(.+?)' on model (.+?)\\. To remedy this, change the \"as\" options in your association definition","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/associations/helpers.ts","lineNumber":26,"sourceCode":"import { AssociationError } from '../errors/index.js';\nimport type { Model, ModelStatic } from '../model';\nimport type { Sequelize } from '../sequelize';\nimport * as deprecations from '../utils/deprecations.js';\nimport { isModelStatic, isSameInitialModel } from '../utils/model-utils.js';\nimport { removeUndefined } from '../utils/object.js';\nimport { pluralize, singularize } from '../utils/string.js';\nimport type { OmitConstructors } from '../utils/types.js';\nimport type {\n  Association,\n  AssociationOptions,\n  ForeignKeyOptions,\n  NormalizedAssociationOptions,\n} from './base';\nimport type { ThroughOptions } from './belongs-to-many.js';\n\nexport function checkNamingCollision(source: ModelStatic<any>, associationName: string): void {\n  if (Object.hasOwn(source.getAttributes(), associationName)) {\n    throw new Error(\n      `Naming collision between attribute '${associationName}'` +\n        ` and association '${associationName}' on model ${source.name}` +\n        '. To remedy this, change the \"as\" options in your association definition',\n    );\n  }\n}\n\n/**\n * Mixin (inject) association methods to model prototype\n *\n * @private\n *\n * @param association instance\n * @param mixinTargetPrototype Model prototype\n * @param methods Method names to inject\n * @param aliases Mapping between model and association method names\n */\nexport function mixinMethods<A extends Association, Aliases extends Record<string, string>>(","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/sequelize/sequelize/blob/7e1deec499d5afbb8d1877c2f4d545cead1214ec/packages/core/src/associations/helpers.ts#L8-L44","documentation":"Thrown by checkNamingCollision when an association's resolved name (the 'as' value) exactly matches the name of an already-defined attribute on the same source model. Sequelize injects association accessors/getters as properties on model instances, so a name clash would silently overwrite the attribute getter and produce corrupt queries. The error is raised eagerly (before construction at helpers.ts:209 and again after at helpers.ts:246) to prevent ambiguous property resolution.","triggerScenarios":"Calling Source.hasMany(Target) / Source.belongsTo(Target) / etc. where the computed association alias equals an attribute key returned by source.getAttributes(). The alias is computed from options.as, or when omitted from the target model's singular/plural name (see normalizeBaseAssociationOptions, helpers.ts:294-313). Also triggered by association decorators whose field name matches an attribute.","commonSituations":"Defining a belongsTo to a 'User' target that resolves to alias 'user' while the source already has a column literally named 'user'. Singularizing/pluralizing producing an alias that collides with a foreignKey whose name matches. Mixing association decorators with attributes of the same field name.","solutions":["Set an explicit 'as' option on the association so its alias differs from the conflicting attribute name.","Rename the conflicting attribute (or its columnName) so the model attribute key no longer matches the association alias.","If using decorators, rename the decorated class field so it does not collide with a declared attribute.","Audit source.getAttributes() keys vs the resolved 'as' to confirm which name is colliding."],"exampleFix":"// before\nUser.init({ profile: DataTypes.STRING }, ...);\nUser.belongsTo(Profile, { foreignKey: 'profileId' }); // 'profile' alias collides with attribute 'profile'\n\n// after\nUser.belongsTo(Profile, { as: 'userProfile', foreignKey: 'profileId' });","handlingStrategy":"validation","validationCode":"import type { ModelStatic } from '@sequelize/core';\n\nfunction assertNoAssociationNameCollision(\n  source: ModelStatic<any>,\n  as: string,\n): void {\n  const attrs = source.getAttributes();\n  if (Object.prototype.hasOwnProperty.call(attrs, as)) {\n    throw new Error(`Proposed association alias '${as}' collides with existing attribute on ${source.name}`);\n  }\n}\n\n// call before defining the association\nassertNoAssociationNameCollision(User, 'profile');\nUser.belongsTo(Profile, { as: 'profile', foreignKey: 'profileId' });","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass an explicit 'as' that you have verified is not an attribute key.","Centralize association declarations and review them in code review for attribute-name overlap.","When using decorators, ensure field names differ from attribute names."],"tags":["associations","naming","attributes","sequelize-core"],"analyzedSha":"7e1deec499d5afbb8d1877c2f4d545cead1214ec","analyzedAt":"2026-08-03T18:58:44.549Z","schemaVersion":2}