{"id":"1a9726328d8177e8","repo":"drizzle-team/drizzle-orm","slug":"alias-tablename-is-already-used-in-this-query-1a9726","errorCode":null,"errorMessage":"Alias \"${tableName}\" is already used in this query","messagePattern":"Alias \"(.+?)\" is already used in this query","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"drizzle-orm/src/mysql-core/query-builders/select.ts","lineNumber":273,"sourceCode":"\t\t\t\t: 'Index hint configuration is allowed only for MySqlTable and not for subqueries or views',\n\t\t) => {\n\t\t\tconst isCrossJoin = joinType === 'cross';\n\t\t\tlet on = (isCrossJoin ? undefined : a) as (\n\t\t\t\t| ((aliases: TSelection) => SQL | undefined)\n\t\t\t\t| SQL\n\t\t\t\t| undefined\n\t\t\t);\n\t\t\tconst onIndex = (isCrossJoin ? a : b) as TJoinedTable extends MySqlTable ? IndexConfig\n\t\t\t\t: 'Index hint configuration is allowed only for MySqlTable and not for subqueries or views';\n\n\t\t\tconst baseTableName = this.tableName;\n\t\t\tconst tableName = getTableLikeName(table);\n\n\t\t\t// store all tables used in a query\n\t\t\tfor (const item of extractUsedTable(table)) this.usedTables.add(item);\n\n\t\t\tif (typeof tableName === 'string' && this.config.joins?.some((join) => join.alias === tableName)) {\n\t\t\t\tthrow new Error(`Alias \"${tableName}\" is already used in this query`);\n\t\t\t}\n\n\t\t\tif (!this.isPartialSelect) {\n\t\t\t\t// If this is the first join and this is not a partial select and we're not selecting from raw SQL, \"move\" the fields from the main table to the nested object\n\t\t\t\tif (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === 'string') {\n\t\t\t\t\tthis.config.fields = {\n\t\t\t\t\t\t[baseTableName]: this.config.fields,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tif (typeof tableName === 'string' && !is(table, SQL)) {\n\t\t\t\t\tconst selection = is(table, Subquery)\n\t\t\t\t\t\t? table._.selectedFields\n\t\t\t\t\t\t: is(table, View)\n\t\t\t\t\t\t? table[ViewBaseConfig].selectedFields\n\t\t\t\t\t\t: table[Table.Symbol.Columns];\n\t\t\t\t\tthis.config.fields[tableName] = selection;\n\t\t\t\t}\n\t\t\t}","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/drizzle-team/drizzle-orm/blob/b7862528fd8fc39bc2653a6c18dad7c1f4e68d10/drizzle-orm/src/mysql-core/query-builders/select.ts#L255-L291","documentation":"Thrown by createJoin inside MySqlSelectQueryBuilderBase (line 273) when a join is added whose alias already exists among the previously registered joins. Drizzle prevents duplicate aliases because they'd produce ambiguous SQL.","triggerScenarios":"Calling two joins with the same table/alias, e.g. .leftJoin(pets, ...).leftJoin(pets, ...) or joining an aliased table whose alias was already used. The check scans config.joins for a matching alias.","commonSituations":"Self-joins done without distinct aliases; joining the same relation twice (e.g. owner + co-owner); copy-pasting a join without renaming the alias.","solutions":["Alias the second instance distinctly: .leftJoin(pets.as('pet1'), ...).leftJoin(pets.as('pet2'), ...).","Remove the duplicate join if it was added by mistake.","For self-joins, create two aliased references to the same table up front and join each once."],"exampleFix":"// before\ndb.select().from(users)\n  .leftJoin(pets, eq(users.id, pets.ownerId))\n  .leftJoin(pets, eq(users.id, pets.coOwnerId)); // duplicate 'pets'\n\n// after - alias the second\nconst pet1 = pets.as('pet1');\nconst pet2 = pets.as('pet2');\ndb.select().from(users)\n  .leftJoin(pet1, eq(users.id, pet1.ownerId))\n  .leftJoin(pet2, eq(users.id, pet2.coOwnerId));","handlingStrategy":"validation","validationCode":"const usedAliases = new Set<string>();\nfunction assertAlias(alias: string) {\n  if (usedAliases.has(alias)) throw new Error(`Alias ${alias} already used`);\n  usedAliases.add(alias);\n}","typeGuard":"function aliasAvailable(existing: string[], alias: string): boolean {\n  return !existing.includes(alias);\n}","tryCatchPattern":null,"preventionTips":["Use distinct aliases (.as('name')) for repeated table joins.","Track used aliases when building joins dynamically.","Avoid joining the same table twice without aliasing."],"tags":["mysql","select","joins","alias","validation"],"analyzedSha":"b7862528fd8fc39bc2653a6c18dad7c1f4e68d10","analyzedAt":"2026-08-03T18:11:14.318Z","schemaVersion":2}