Budibase/budibase · error · Error
Unable to generate link schema, no primary keys
Error message
Unable to generate link schema, no primary keys
What it means
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.
Source
Thrown at packages/server/src/sdk/workspace/tables/external/utils.ts:132
},
}
column.through = junctionTable._id
column.throughFrom = relatedPrimary
column.throughTo = primary
column.fieldName = relatedPrimary
return junctionTable
}
export function generateLinkSchema(
column:
| OneToManyRelationshipFieldMetadata
| ManyToOneRelationshipFieldMetadata,
table: Table,
relatedTable: Table,
type: RelationshipType.ONE_TO_MANY | RelationshipType.MANY_TO_ONE
) {
if (!table.primary || !relatedTable.primary) {
throw new Error("Unable to generate link schema, no primary keys")
}
const isOneSide = type === RelationshipType.ONE_TO_MANY
const primary = isOneSide ? relatedTable.primary[0] : table.primary[0]
// generate a foreign key
const foreignKey = generateForeignKey(column, relatedTable)
column.relationshipType = type
column.foreignKey = isOneSide ? foreignKey : primary
column.fieldName = isOneSide ? primary : foreignKey
return foreignKey
}
export function generateRelatedSchema(
linkColumn: RelationshipFieldMetadata,
table: Table,
relatedTable: Table,
columnName: string
) {
// generate column for other tableView on GitHub (pinned to a81a902e9a)
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
Example fix
// before // neither table has primary defined await tables.external.save(datasourceId, tableWithLinkColumn) // after table.primary = ["id"] relatedTable.primary = ["id"] await tables.external.save(datasourceId, tableWithLinkColumn)
Defensive patterns
Strategy: validation
Validate before calling
if (!table.primary?.length && !relatedTable.primary?.length) {
throw new Error("Link requires a primary key on at least one table")
} Type guard
function linkable(t: Table, related: Table): boolean {
return (t.primary?.length ?? 0) > 0 || (related.primary?.length ?? 0) > 0
} Try / catch
try {
await tables.external.save(datasourceId, table)
} catch (err) {
if (err.message === "Unable to generate link schema, no primary keys") {
// define table.primary or fix PKs in source DB and re-sync
}
} Prevention
- Verify PK detection after initial datasource sync
- Set primary explicitly on imported tables
- Avoid linking tables that lack keys entirely
When it happens
Trigger: Saving a ONE_TO_MANY or MANY_TO_ONE relationship where both table.primary and relatedTable.primary are missing/empty.
Common situations: External SQL tables synced without detected primary keys; legacy tables imported before PK detection; database tables altered to drop PKs after initial sync.
Related errors
- Unable to lookup relationships - undefined column properties
- unable to find related table
- Unable to generate many link schema, "${noPrimaryName}" does
- Source table '${relationship.sourceTable}' not found in data
- Target table '${relationship.targetTable}' not found in data
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/f94e794749b03d9b.
Report an issue: GitHub.