{"id":"f56c84421e1fb041","repo":"drizzle-team/drizzle-orm","slug":"alias-tablename-is-already-used-in-this-query-f56c84","errorCode":null,"errorMessage":"Alias \"${tableName}\" is already used in this query","messagePattern":"Alias \"(.+?)\" is already used in this query","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"drizzle-orm/src/singlestore-core/query-builders/select.ts","lineNumber":228,"sourceCode":"\t\tTIsLateral extends (TJoinType extends 'full' | 'right' ? false : boolean),\n\t>(\n\t\tjoinType: TJoinType,\n\t\tlateral: TIsLateral,\n\t): 'cross' extends TJoinType ? SingleStoreCrossJoinFn<this, TDynamic, TIsLateral>\n\t\t: SingleStoreJoinFn<this, TDynamic, TJoinType, TIsLateral>\n\t{\n\t\treturn (\n\t\t\ttable: SingleStoreTable | Subquery | SQL, // | SingleStoreViewBase\n\t\t\ton?: ((aliases: TSelection) => SQL | undefined) | SQL | undefined,\n\t\t) => {\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":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/drizzle-team/drizzle-orm/blob/b7862528fd8fc39bc2653a6c18dad7c1f4e68d10/drizzle-orm/src/singlestore-core/query-builders/select.ts#L210-L246","documentation":"Thrown in createJoin (select.ts:228) when adding a join whose resolved table alias already exists in this.config.joins. Drizzle requires each joined source to have a unique alias because field resolution and nullability tracking depend on alias uniqueness.","triggerScenarios":"Joining the same table twice without aliasing the second instance via `.as('alias')`; joining a table whose name collides with the FROM table's name; joining two subqueries both aliased to the same string.","commonSituations":"Self-joins (e.g. users joined to users for manager relationships) without an alias; copy-pasting a join clause; joining a table and a subquery that derive the same alias.","solutions":["Alias at least one of the conflicting tables: `users.as('manager')` and join that aliased instance.","Rename the subquery alias so it doesn't collide with an existing join or the FROM table.","If you truly need the same table twice, give each occurrence a distinct `.as(...)`."],"exampleFix":"// before\nawait db.select()\n  .from(users)\n  .leftJoin(pets, eq(users.id, pets.ownerId))\n  .leftJoin(pets, eq(users.id, pets.secondaryOwnerId));\n// after\nconst secondaryPets = pets.as('secondaryPets');\nawait db.select()\n  .from(users)\n  .leftJoin(pets, eq(users.id, pets.ownerId))\n  .leftJoin(secondaryPets, eq(users.id, secondaryPets.secondaryOwnerId));","handlingStrategy":"validation","validationCode":"function assertUniqueAliases(joins) {\n  const seen = new Set();\n  for (const j of joins) {\n    if (j.alias && seen.has(j.alias)) throw new Error(`Duplicate join alias ${j.alias}`);\n    if (j.alias) seen.add(j.alias);\n  }\n}","typeGuard":"function areJoinAliasesUnique(joins) {\n  const aliases = joins.map((j) => j.alias).filter(Boolean);\n  return new Set(aliases).size === aliases.length;\n}","tryCatchPattern":null,"preventionTips":["Alias self-joined tables with .as('role').","When joining the same table twice, give each a distinct alias.","Audit join lists after copy-pasting clauses."],"tags":["join","alias","singlestore","self-join"],"analyzedSha":"b7862528fd8fc39bc2653a6c18dad7c1f4e68d10","analyzedAt":"2026-08-03T18:11:14.318Z","schemaVersion":2}