{"record":{"id":"5f04a9b708bc8055","repo":"toeverything/AFFiNE","slug":"table-tablename-field-name-can-t-be-ma","errorCode":null,"errorMessage":"[Table(${tableName})]: Field '${name}' can't be marked primary key and optional with no default value provider at the same time.","messagePattern":"\\[Table\\((.+?)\\)\\]: Field '(.+?)' can't be marked primary key and optional with no default value provider at the same time\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/common/infra/src/orm/core/validators/schema.ts","lineNumber":35,"sourceCode":"      for (const name in table) {\n        if (table[name].schema.isPrimaryKey) {\n          primaryFields.push(name);\n        }\n      }\n\n      if (primaryFields.length > 1) {\n        throw new Error(\n          `[Table(${tableName})]: There should be only one field marked as primary key. Found [${primaryFields.join(', ')}].`\n        );\n      }\n    },\n  },\n  PrimaryKeyShouldNotBeOptional: {\n    validate(tableName, table) {\n      for (const name in table) {\n        const opts = table[name].schema;\n        if (opts.isPrimaryKey && opts.optional && !opts.default) {\n          throw new Error(\n            `[Table(${tableName})]: Field '${name}' can't be marked primary key and optional with no default value provider at the same time.`\n          );\n        }\n      }\n    },\n  },\n};\n","sourceCodeStart":17,"sourceCodeEnd":43,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/b4c8548c09da21b2898443559a5b846f0ccf5dd8/packages/common/infra/src/orm/core/validators/schema.ts#L17-L43","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nid: t.string().primaryKey().optional()\n\n// after\nid: t.string().primaryKey().default(nanoid)","handlingStrategy":"validation","validationCode":"for (const [name, f] of Object.entries(fields)) {\n  if (f.isPrimaryKey && f.optional && !f.default) {\n    throw new Error(`field '${name}': primary key must be required or have a default`);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["orm","schema","primary-key","affine"],"backgroundTag":"primary-key-configuration","analyzedSha":"b4c8548c09da21b2898443559a5b846f0ccf5dd8","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}