{"record":{"id":"36cda3f0b5e064de","repo":"hcengineering/platform","slug":"notification-id-is-required","errorCode":null,"errorMessage":"Notification id is required","messagePattern":"Notification id is required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"foundations/communication/packages/shared/src/processor.ts","lineNumber":117,"sourceCode":"      lastView: event.updates.lastView ?? context.lastView,\n      lastUpdate: event.updates.lastUpdate ?? context.lastUpdate,\n      lastNotify: event.updates.lastNotify ?? context.lastNotify\n    }\n  }\n\n  static remove (context: NotificationContext, event: RemoveNotificationContextEvent): NotificationContext | undefined {\n    if (context.account !== event.account || context.id !== event.contextId) return context\n    return undefined\n  }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-extraneous-class\nexport class NotificationProcessor {\n  static create (event: CreateNotificationEvent, id?: NotificationID): Notification {\n    const notificationId: NotificationID | undefined = event.notificationId ?? (id as NotificationID)\n\n    if (notificationId == null) {\n      throw new Error('Notification id is required')\n    }\n    return {\n      id: notificationId,\n      cardId: event.cardId,\n      contextId: event.contextId,\n      account: event.account,\n      type: event.notificationType,\n      read: event.read,\n      content: event.content ?? {},\n      created: event.date ?? new Date(),\n      messageId: event.messageId,\n      creator: event.creator,\n      blobId: event.blobId\n    }\n  }\n}\n\nfunction applyPatchEvent (message: Message, event: PatchEvent): Message | undefined {","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/communication/packages/shared/src/processor.ts#L99-L135","documentation":"NotificationProcessor.create builds a Notification object from a CreateNotificationEvent and an optional explicit id. The event's notificationId is preferred, falling back to the optional second `id` argument. If neither source yields a value (null or undefined), the processor cannot key the notification and throws this error.","triggerScenarios":"Calling NotificationProcessor.create(event) with an event whose notificationId is null/undefined AND omitting the second `id` argument, or passing undefined/null explicitly for it.","commonSituations":"Constructing a CreateNotificationEvent by hand and forgetting to assign notificationId; a deserialized event payload missing the field; refactored call sites that dropped the second argument after relying on it.","solutions":["Set notificationId on the CreateNotificationEvent before calling create","Pass the id as the second argument: NotificationProcessor.create(event, someNotificationId)","Generate an id at the call site (e.g. the ID factory/uuid used elsewhere in the codebase) and provide it to create"],"exampleFix":"// before\nconst notification = NotificationProcessor.create({ cardId, contextId, account });\n// after\nconst notification = NotificationProcessor.create({ cardId, contextId, account, notificationId: generateNotificationId() });","handlingStrategy":"validation","validationCode":"if (event.notificationId == null && id == null) throw new Error('notificationId must be provided before calling NotificationProcessor.create');","typeGuard":"function hasNotificationId(e: CreateNotificationEvent, id?: NotificationID): e is CreateNotificationEvent & { notificationId: NotificationID } { return e.notificationId != null || id != null; }","tryCatchPattern":"let notification;\ntry { notification = NotificationProcessor.create(event, id); }\ncatch (e) { if ((e as Error).message === 'Notification id is required') { /* supply/generate id and retry */ } else throw e; }","preventionTips":["Always assign notificationId when constructing CreateNotificationEvent","Centralize id generation in one factory used by all event producers","Add a schema/validator for event payloads deserialized from queues or storage"],"tags":["missing-argument","validation","notifications"],"backgroundTag":"missing-required-identifier","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}