toeverything/AFFiNE · error · Error
[Table(${tableName})]: There should be at least one field ma
Error message
[Table(${tableName})]: There should be at least one field marked as primary key. What it means
Schema validator PrimaryKeyShouldExist runs when a table definition is registered and throws if not a single field has isPrimaryKey set. Every AFFiNE ORM table must declare exactly one primary key so rows can be addressed for get/update/delete. This fails at definition time, before any data operation.
Source
Thrown at packages/common/infra/src/orm/core/validators/schema.ts:7
import type { TableSchemaValidator } from './types';
export const tableSchemaValidators: Record<string, TableSchemaValidator> = {
PrimaryKeyShouldExist: {
validate(tableName, table) {
if (!Object.values(table).some(field => field.schema.isPrimaryKey)) {
throw new Error(
`[Table(${tableName})]: There should be at least one field marked as primary key.`
);
}
},
},
OnlyOnePrimaryKey: {
validate(tableName, table) {
const primaryFields = [];
for (const name in table) {
if (table[name].schema.isPrimaryKey) {
primaryFields.push(name);
}
}
if (primaryFields.length > 1) {
throw new Error(
`[Table(${tableName})]: There should be only one field marked as primary key. Found [${primaryFields.join(', ')}].`View on GitHub (pinned to b4c8548c09)
Solutions
- Add .primaryKey() to the field that uniquely identifies rows (usually an id column).
- If no natural unique column exists, add an id: t.string().primaryKey() and populate it (e.g. with nanoid/uuid) on create.
- Re-run; this throws eagerly at table registration, so the stack points straight at the offending definition.
Example fix
// before
export const Setting = t.table('setting', {
key: t.string(),
value: t.string(),
});
// after
export const Setting = t.table('setting', {
key: t.string().primaryKey(),
value: t.string(),
}); Defensive patterns
Strategy: validation
Validate before calling
function assertSinglePrimaryKey(tableName: string, fields: Record<string, { isPrimaryKey?: boolean }>) {
const pks = Object.entries(fields).filter(([, f]) => f.isPrimaryKey);
if (pks.length === 0) throw new Error(`${tableName}: missing primary key`);
if (pks.length > 1) throw new Error(`${tableName}: multiple primary keys ${pks.map(([n]) => n)}`);
} Try / catch
try { registerTable(MyTable); } catch (e) { if (e instanceof Error && e.message.includes('primary key')) { /* fix definition; fails fast at startup */ } throw e; } Prevention
- Start new table definitions from a template containing id: t.string().primaryKey().default(nanoid)
- Register tables in a unit test so definition errors fail CI, not production
- Code-review any schema diff for PK presence
When it happens
Trigger: Calling t.table('name', {...}) where no field uses .primaryKey(); defining the table with only plain t.string()/t.number() fields; forgetting .primaryKey() when copying an existing table definition.
Common situations: Creating a new table quickly during prototyping and skipping the key; refactoring a table and accidentally dropping the .primaryKey() chain; generating table definitions from a template that lacks the marker.
Related errors
- [Table(${tableName})]: There should be only one field marked
- [Table(${tableName})]: Field '${name}' can't be marked prima
- ValueNotExists
- EdgelessExportError
- ValueNotExists
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/12af8699dbb92a45.
Report an issue: GitHub.