{"record":{"id":"8ec149b29ea97503","repo":"Budibase/budibase","slug":"junction-table-already-exists-cannot-create-anoth","errorCode":null,"errorMessage":"Junction table already exists, cannot create another relationship.","messagePattern":"Junction table already exists, cannot create another relationship\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/sdk/workspace/tables/external/index.ts","lineNumber":206,"sourceCode":"    }\n    const schemaTableId = schema.tableId\n    const relatedTable = Object.values(tables).find(\n      table => table._id === schemaTableId\n    )\n    if (!relatedTable) {\n      continue\n    }\n    const relatedColumnName = schema.fieldName!\n    const relationType = schema.relationshipType\n    if (relationType === RelationshipType.MANY_TO_MANY) {\n      const junctionTable = generateManyLinkSchema(\n        datasource,\n        schema,\n        tableToSave,\n        relatedTable\n      )\n      if (tables[junctionTable.name]) {\n        throw new Error(\n          \"Junction table already exists, cannot create another relationship.\"\n        )\n      }\n      tables[junctionTable.name] = junctionTable\n      extraTablesToUpdate.push(junctionTable)\n    } else {\n      const fkTable =\n        relationType === RelationshipType.ONE_TO_MANY\n          ? tableToSave\n          : relatedTable\n      const foreignKey = generateLinkSchema(\n        schema,\n        tableToSave,\n        relatedTable,\n        relationType\n      )\n      if (fkTable.schema[foreignKey] != null) {\n        throw new Error(","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/tables/external/index.ts#L188-L224","documentation":"When saving a many-to-many relationship for external datasources, save() generates a junction table. If a table with the same generated junction name already exists in the datasource, creating another would collide, so it throws. This prevents duplicate/ambiguous join tables.","triggerScenarios":"Adding a many-to-many column whose generated junction table name (from table names + column names) matches an existing table in the datasource, then calling save().","commonSituations":"Two relationships between the same pair of tables producing identical junction names; re-running a migration that already created the junction table; renaming columns so generated names collide.","solutions":["Remove or rename the existing junction table relationship before adding the new one","Change the column/table names so the generated junction table name is unique","Drop the stale junction table in the connected database and refresh the datasource entities","Recreate the relationship once, avoiding repeated saves that re-create it"],"exampleFix":"// before\n\"users\": { manyToMany: \"user_groups\" } // junction user_groups_users already exists\n// after\ndelete stale junction relationship, then\n\"users\": { manyToMany: \"memberships\" } // unique junction name generated","handlingStrategy":"validation","validationCode":"const junctionName = generateJunctionTableName(column, table, relatedTable)\nconst entities = await tables.external.getExternalTablesInDatasource(datasourceId)\nif (entities[junctionName]) throw new Error(`Junction ${junctionName} already exists`)","typeGuard":"function junctionAvailable(entities: Record<string, Table>, name: string): boolean {\n  return entities[name] == null\n}","tryCatchPattern":"try {\n  await tables.external.save(datasourceId, table)\n} catch (err) {\n  if (err.message.includes(\"Junction table already exists\")) {\n    // reuse existing relationship or drop the junction table first\n  }\n}","preventionTips":["Check for existing relationships before re-adding many-to-many columns","Avoid duplicate relationship definitions between the same table pair","Refresh datasource entities after manual DB changes"],"tags":["external-datasource","many-to-many","naming-collision"],"backgroundTag":"table-name-collision","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}