{"record":{"id":"f94e794749b03d9b","repo":"Budibase/budibase","slug":"unable-to-generate-link-schema-no-primary-keys","errorCode":null,"errorMessage":"Unable to generate link schema, no primary keys","messagePattern":"Unable to generate link schema, no primary keys","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/sdk/workspace/tables/external/utils.ts","lineNumber":132,"sourceCode":"    },\n  }\n  column.through = junctionTable._id\n  column.throughFrom = relatedPrimary\n  column.throughTo = primary\n  column.fieldName = relatedPrimary\n  return junctionTable\n}\n\nexport function generateLinkSchema(\n  column:\n    | OneToManyRelationshipFieldMetadata\n    | ManyToOneRelationshipFieldMetadata,\n  table: Table,\n  relatedTable: Table,\n  type: RelationshipType.ONE_TO_MANY | RelationshipType.MANY_TO_ONE\n) {\n  if (!table.primary || !relatedTable.primary) {\n    throw new Error(\"Unable to generate link schema, no primary keys\")\n  }\n  const isOneSide = type === RelationshipType.ONE_TO_MANY\n  const primary = isOneSide ? relatedTable.primary[0] : table.primary[0]\n  // generate a foreign key\n  const foreignKey = generateForeignKey(column, relatedTable)\n  column.relationshipType = type\n  column.foreignKey = isOneSide ? foreignKey : primary\n  column.fieldName = isOneSide ? primary : foreignKey\n  return foreignKey\n}\n\nexport function generateRelatedSchema(\n  linkColumn: RelationshipFieldMetadata,\n  table: Table,\n  relatedTable: Table,\n  columnName: string\n) {\n  // generate column for other table","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/tables/external/utils.ts#L114-L150","documentation":"generateLinkSchema creates one-to-many/many-to-one link columns, which requires a primary key on at least one side to anchor the foreign key. If neither table defines primary keys, it throws this generic message.","triggerScenarios":"Saving a ONE_TO_MANY or MANY_TO_ONE relationship where both table.primary and relatedTable.primary are missing/empty.","commonSituations":"External SQL tables synced without detected primary keys; legacy tables imported before PK detection; database tables altered to drop PKs after initial sync.","solutions":["Define a primary key on the related table in the source database and re-sync","Set table.primary (e.g. [\"id\"]) on the Budibase table before creating the link","Pick a keyed table for the relationship","Refresh the datasource to re-run table metadata detection"],"exampleFix":"// before\n// neither table has primary defined\nawait tables.external.save(datasourceId, tableWithLinkColumn)\n// after\ntable.primary = [\"id\"]\nrelatedTable.primary = [\"id\"]\nawait tables.external.save(datasourceId, tableWithLinkColumn)","handlingStrategy":"validation","validationCode":"if (!table.primary?.length && !relatedTable.primary?.length) {\n  throw new Error(\"Link requires a primary key on at least one table\")\n}","typeGuard":"function linkable(t: Table, related: Table): boolean {\n  return (t.primary?.length ?? 0) > 0 || (related.primary?.length ?? 0) > 0\n}","tryCatchPattern":"try {\n  await tables.external.save(datasourceId, table)\n} catch (err) {\n  if (err.message === \"Unable to generate link schema, no primary keys\") {\n    // define table.primary or fix PKs in source DB and re-sync\n  }\n}","preventionTips":["Verify PK detection after initial datasource sync","Set primary explicitly on imported tables","Avoid linking tables that lack keys entirely"],"tags":["external-datasource","relationships","missing-primary-key"],"backgroundTag":"missing-primary-key","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}