Budibase/budibase · error · Error

Unable to generate many link schema, "${noPrimaryName}" does

Error message

Unable to generate many link schema, "${noPrimaryName}" does not have a primary key

What it means

generateManyLinkSchema builds junction tables for many-to-many relationships, which requires primary keys on both tables to compose the join columns. If either table lacks a primary key definition, it throws naming the offending table.

Source

Thrown at packages/server/src/sdk/workspace/tables/external/utils.ts:88

export function otherRelationshipType(type: RelationshipType) {
  if (type === RelationshipType.MANY_TO_MANY) {
    return RelationshipType.MANY_TO_MANY
  }
  return type === RelationshipType.ONE_TO_MANY
    ? RelationshipType.MANY_TO_ONE
    : RelationshipType.ONE_TO_MANY
}

export function generateManyLinkSchema(
  datasource: Datasource,
  column: ManyToManyRelationshipFieldMetadata,
  table: Table,
  relatedTable: Table
): Table {
  if (!table.primary || !relatedTable.primary) {
    const noPrimaryName = !table.primary ? table.name : relatedTable.name
    throw new Error(
      `Unable to generate many link schema, "${noPrimaryName}" does not have a primary key`
    )
  }
  const primary = table.name + table.primary[0]
  const relatedPrimary = relatedTable.name + relatedTable.primary[0]
  const jcTblName = generateJunctionTableName(column, table, relatedTable)
  const datasourceId = datasource._id!
  // first create the new table
  const junctionTable: Table = {
    type: "table",
    _id: buildExternalTableId(datasourceId, jcTblName),
    name: jcTblName,
    primary: [primary, relatedPrimary],
    constrained: [primary, relatedPrimary],
    sourceId: datasourceId,
    sourceType: TableSourceType.EXTERNAL,
    schema: {
      [primary]: foreignKeyStructure(primary, {

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Add a primary key to the affected table in the connected SQL database and re-sync the datasource
  2. Set table.primary in the Budibase table schema before creating the relationship
  3. Use a table with a defined primary key for the many-to-many relationship
  4. Refresh datasource entities so the connector re-detects keys

Example fix

// before
table.primary === undefined
// after
table.primary = ["id"]
await tables.external.save(datasourceId, table)
Defensive patterns

Strategy: validation

Validate before calling

if (!table.primary?.length || !relatedTable.primary?.length) {
  throw new Error("Both tables need a primary key for many-to-many links")
}

Type guard

function hasPrimaryKey(t: Table): t is Table & { primary: string[] } {
  return Array.isArray(t.primary) && t.primary.length > 0
}

Try / catch

try {
  await tables.external.save(datasourceId, table)
} catch (err) {
  if (err.message.includes("does not have a primary key")) {
    // add a PK in the source DB and re-sync before retrying
  }
}

Prevention

When it happens

Trigger: Saving a many-to-many relationship where table.primary or relatedTable.primary is undefined/empty — typically external SQL tables synced without a detected primary key.

Common situations: Imported SQL tables without primary keys; views or tables where the connector failed to detect the PK; schema sync after a PK was dropped in the database.

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/5ff68831e53566bd. Report an issue: GitHub.