{"record":{"id":"075682ca76d1e1aa","repo":"nocobase/nocobase","slug":"collection-model-this-collection-model-name-has","errorCode":null,"errorMessage":"Collection model ${this.collection.model.name} has no primary key attribute","messagePattern":"Collection model (.+?) has no primary key attribute","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/database/src/fields/belongs-to-many-field.ts","lineNumber":135,"sourceCode":"    if (!this.keyPairsTypeMatched(otherKeyType, targetKeyType)) {\n      throw new Error(\n        `Other key \"${otherKey}\" type \"${otherKeyType}\" does not match target key \"${targetKey}\" type \"${targetKeyType}\" in belongs to many relation \"${this.name}\" of collection \"${this.collection.name}\"`,\n      );\n    }\n  }\n\n  bind() {\n    const { database, collection } = this.context;\n\n    const Target = this.TargetModel;\n\n    if (!Target) {\n      database.addPendingField(this);\n      return false;\n    }\n\n    if (!this.collection.model.primaryKeyAttribute) {\n      throw new Error(`Collection model ${this.collection.model.name} has no primary key attribute`);\n    }\n\n    if (!Target.primaryKeyAttribute) {\n      throw new Error(`Target model ${Target.name} has no primary key attribute`);\n    }\n\n    this.checkAssociationKeys(database);\n\n    const through = this.through;\n\n    let Through: Collection;\n\n    if (database.hasCollection(through)) {\n      Through = database.getCollection(through);\n      Through.options.sourceCollectionName ??= this.collection.name;\n      Through.options.targetCollectionName ??= this.target;\n    } else {\n      const throughCollectionOptions = {","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/nocobase/nocobase/blob/fa42722fefe44265490dff2c27d79e2882bce4fa/packages/core/database/src/fields/belongs-to-many-field.ts#L117-L153","documentation":"BelongsToManyField.bind() refuses to create the association when the source collection's Sequelize model has no primary key attribute, because a many-to-many JOIN requires a source key to link through the pivot table. NocoBase throws this early at bind time instead of letting Sequelize produce confusing SQL errors later.","triggerScenarios":"Calling database.collection() / addField with a belongsToMany field on a collection whose model has no primaryKeyAttribute — typically a collection defined without any primary key field, or whose PK was removed/renamed — when the field is bound (bind() after the target exists).","commonSituations":"Defining a collection where every field is non-primary (all type options missing primaryKey: true); a migration or dump/restore that dropped the PK column; a custom collection whose fields failed to sync so the PK column doesn't exist; typo in the pk field name so it isn't recognized.","solutions":["Add a primary key field to the source collection (e.g. { name: 'id', type: 'bigInt', primaryKey: true, autoIncrement: true }).","If the PK exists in the definition but not in the DB, run sync/`yarn nocobase upgrade` so the column is created.","Check for a typo in the PK field name/options and confirm model.primaryKeyAttribute resolves.","Restore the dropped PK column via migration if a previous change removed it.","Rebind the association after the PK exists."],"exampleFix":"// before\ndatabase.collection({ name: 'posts', fields: [\n  { name: 'title', type: 'string' },\n]});\n// after\ndatabase.collection({ name: 'posts', fields: [\n  { name: 'id', type: 'bigInt', primaryKey: true, autoIncrement: true },\n  { name: 'title', type: 'string' },\n]});","handlingStrategy":"validation","validationCode":"function assertHasPrimaryKey(db, collectionName) {\n  const c = db.getCollection(collectionName);\n  if (!c || !c.model.primaryKeyAttribute) {\n    throw new Error(`Collection ${collectionName} must define a primary key field before relations bind`);\n  }\n}\n// call before adding belongsToMany fields","typeGuard":"const hasPrimaryKey = (collection) =>\n  Boolean(collection && collection.model && collection.model.primaryKeyAttribute);","tryCatchPattern":"try {\n  db.bindField('posts', 'tags');\n} catch (e) {\n  if (e.message.includes('has no primary key attribute')) {\n    db.collection({ name: 'posts', fields: [{ name: 'id', type: 'bigInt', primaryKey: true, autoIncrement: true }] });\n  } else throw e;\n}","preventionTips":["Always include a primary key field in every collection definition","Use the NocoBase scaffolding/templates that add id by default","Check migrations/dumps preserve PK columns and constraints","Confirm DB sync succeeded (PK column exists) before binding relations","Grep collection definitions for missing primaryKey: true fields in CI"],"tags":["database","sequelize","primary-key","collection-definition"],"backgroundTag":"missing-primary-key","analyzedSha":"fa42722fefe44265490dff2c27d79e2882bce4fa","analyzedAt":"2026-09-01T00:54:31.202Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}