sequelize/sequelize · error · AssociationError
You have defined two associations with the same name "${as}"
Error message
You have defined two associations with the same name "${as}" on the model "${source.name}". Use another alias using the "as" parameter. What it means
Thrown by assertAssociationUnique when a second top-level association (no parent) is declared on the same source model with an identical 'as' alias, and the existing one is the root association. Sequelize keys associations by alias in source.associations, so a duplicate alias would overwrite the previous registration. The guard short-circuits only when the duplicate is fully compatible and nested under a parent; an unparented exact duplicate is always rejected.
Source
Thrown at packages/core/src/associations/helpers.ts:107
const existingAssociation = source.associations[as];
if (!existingAssociation) {
return;
}
const incompatibilityStatus = getAssociationsIncompatibilityStatus(
existingAssociation,
type,
target,
options,
);
if ((parent || existingAssociation.parentAssociation) && incompatibilityStatus == null) {
return;
}
const existingRoot = existingAssociation.rootAssociation;
if (!parent && existingRoot === existingAssociation) {
throw new AssociationError(
`You have defined two associations with the same name "${as}" on the model "${source.name}". Use another alias using the "as" parameter.`,
);
}
throw new AssociationError(
`
${parent ? `The association "${parent.as}" needs to define` : `You are trying to define`} the ${type.name} association "${options.as}" from ${source.name} to ${target.name},
but that child association has already been defined as ${existingAssociation.associationType}, to ${target.name} by this call:
${existingRoot.source.name}.${lowerFirst(existingRoot.associationType)}(${existingRoot.target.name}, ${NodeUtils.inspect(existingRoot.options)})
That association would be re-used if compatible, but it is incompatible because ${
incompatibilityStatus === IncompatibilityStatus.DIFFERENT_TYPES
? `their types are different (${type.name} vs ${existingAssociation.associationType})`
: incompatibilityStatus === IncompatibilityStatus.DIFFERENT_TARGETS
? `they target different models (${target.name} vs ${existingAssociation.target.name})`
: `their options are not reconcilable:
View on GitHub (pinned to 7e1deec499)
Solutions
- Give each association a distinct 'as' alias.
- Remove the redundant duplicate association declaration.
- If two targets legitimately share a name, alias at least one explicitly with 'as'.
- Grep for the alias in the model's association declarations to find the duplicate.
Example fix
// before
User.hasMany(Task, { as: 'tasks' });
User.hasMany(Task, { as: 'tasks' }); // duplicate
// after
User.hasMany(Task, { as: 'tasks' });
User.hasMany(Task, { as: 'assignedTasks' }); Defensive patterns
Strategy: validation
Validate before calling
function assertAliasUnique(source: ModelStatic<any>, as: string): void {
if (source.associations[as]) {
throw new Error(`Alias '${as}' already declared on ${source.name}`);
}
}
assertAliasUnique(User, 'tasks');
User.hasMany(Task, { as: 'tasks' }); Prevention
- Maintain a single setup function per model that declares all associations, so duplicates are visually obvious.
- Lint for repeated 'as' values across association calls on the same source.
- Prefer explicit 'as' over derived aliases to avoid accidental collisions.
When it happens
Trigger: Calling e.g. User.hasMany(Task, { as: 'tasks' }) twice, or two association declarations (any type) whose normalized 'as' resolves to the same string. Occurs when 'as' is omitted and two targets share the same singular/plural name, or when copy-pasting an association block.
Common situations: Defining both a hasMany and a belongsTo that resolve to the same alias. Splitting model setup across files and re-declaring an association. Forgetting that omitting 'as' derives it from the target model name, causing collisions when two targets share names.
Related errors
- Naming collision between attribute '${associationName}' and
- ${parent ? `The association "${parent.as}" needs to define`
- The constraint name must be provided explicitly if one of Se
- Model ${model.name} must be defined (through Model.init or S
- ${source.name}.${lowerFirst(type.name)} was called with ${No
AI-assisted analysis of sequelize/sequelize@7e1deec499 (2026-08-03).
Data as JSON: /data/errors/faf3050ed4c87ab1.json.
Report an issue: GitHub.