toeverything/AFFiNE · error · Error
[Table(${tableName})]: Field '${name}' can't be marked prima
Error message
[Table(${tableName})]: Field '${name}' can't be marked primary key and optional with no default value provider at the same time. What it means
Schema validator PrimaryKeyShouldNotBeOptional rejects a field that is simultaneously a primary key, optional, and has no default provider. Such a field could be absent, which would make the row unaddressable — the ORM cannot look up or update a row with no key, so the configuration is banned up front.
Source
Thrown at packages/common/infra/src/orm/core/validators/schema.ts:35
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(', ')}].`
);
}
},
},
PrimaryKeyShouldNotBeOptional: {
validate(tableName, table) {
for (const name in table) {
const opts = table[name].schema;
if (opts.isPrimaryKey && opts.optional && !opts.default) {
throw new Error(
`[Table(${tableName})]: Field '${name}' can't be marked primary key and optional with no default value provider at the same time.`
);
}
}
},
},
};
View on GitHub (pinned to b4c8548c09)
Solutions
- Add a default provider so the key is always generated: t.string().primaryKey().default(nanoid).
- Or drop .optional() so callers must always supply the key explicitly.
- Keep exactly one of: required key, or optional key with default — never optional-without-default.
Example fix
// before id: t.string().primaryKey().optional() // after id: t.string().primaryKey().default(nanoid)
Defensive patterns
Strategy: validation
Validate before calling
for (const [name, f] of Object.entries(fields)) {
if (f.isPrimaryKey && f.optional && !f.default) {
throw new Error(`field '${name}': primary key must be required or have a default`);
}
} Prevention
- Always pair .primaryKey() with either nothing (required) or .default(nanoid) — never .optional() alone
- Use one canonical id-field pattern across all tables
- Registering tables in tests catches this at build time
When it happens
Trigger: Declaring id: t.string().primaryKey().optional() with no .default(...); marking a key optional to make inserts 'easier'; refactoring a previously-required key into optional during a migration.
Common situations: Wanting auto-generated ids but marking optional instead of providing a default generator; inconsistency introduced when copying a field definition chain and dropping the default part.
Related errors
- [Table(${tableName})]: There should be at least one field ma
- [Table(${tableName})]: There should be only one field marked
- ValueNotExists
- EdgelessExportError
- ValueNotExists
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/5f04a9b708bc8055.
Report an issue: GitHub.