{"record":{"id":"5f5b4f418ccffe7d","repo":"hcengineering/platform","slug":"message-id-is-required","errorCode":null,"errorMessage":"Message id is required","messagePattern":"Message id is required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"foundations/communication/packages/server/src/middleware/storage.ts","lineNumber":232,"sourceCode":"\n  private async addCollaborators (event: Enriched<AddCollaboratorsEvent>): Promise<Result> {\n    const added = await this.db.addCollaborators(event.cardId, event.cardType, event.collaborators, event.date)\n\n    if (added.length === 0) return { skipPropagate: true }\n    event.collaborators = added\n    return {}\n  }\n\n  private async removeCollaborators (event: Enriched<RemoveCollaboratorsEvent>): Promise<Result> {\n    if (event.collaborators.length === 0) return { skipPropagate: true }\n    await this.db.removeCollaborators({ cardId: event.cardId, account: event.collaborators })\n\n    return {}\n  }\n\n  private async createMessage (event: Enriched<CreateMessageEvent>): Promise<Result> {\n    if (event.messageId == null) {\n      throw new Error('Message id is required')\n    }\n\n    const group = await this.blob.getMessageGroupByDate(event.cardId, event.date)\n    if (group == null) {\n      throw new Error(\n        `Cannot create message, group not found: cardId = ${event.cardId}, messageId = ${event.messageId}, created = ${event.date.toISOString()}`\n      )\n    }\n    const result: CreateMessageResult = {\n      messageId: event.messageId,\n      created: event.date,\n      blobId: group.blobId\n    }\n    const created = await this.db.createMessageMeta(\n      event.cardId,\n      event.messageId,\n      event.socialId,\n      event.date,","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/communication/packages/server/src/middleware/storage.ts#L214-L250","documentation":"The storage middleware's createMessage handler validates that an incoming CreateMessageEvent carries a messageId before writing to blob storage. If `event.messageId == null` (undefined or null), it throws this Error. The message group lookup cannot proceed without a stable message identity.","triggerScenarios":"processEvent routing a CreateMessageEvent to storage middleware when the event was constructed without messageId and no external id was supplied upstream.","commonSituations":"Producers emitting message-created events before assigning an id; serialization dropping undefined messageId fields; a client generating events locally without an id; mismatch between event schema versions where messageId became optional in the producer.","solutions":["Ensure the producer assigns messageId (or pass an explicit id via MessageProcessor.create's `id` argument) before dispatching the event.","Add validation at event ingestion to reject CreateMessageEvent without messageId early, with a clear log.","Check serialization/deserialization (JSON.stringify drops undefined fields) — generate the id server-side if missing instead of failing.","Align event schema versions between producer and the communication server."],"exampleFix":"// before\nawait processor.handle({ type: 'message.create', cardId, content } as CreateMessageEvent)\n// Error: Message id is required\n// after\nawait processor.handle({ type: 'message.create', cardId, messageId: crypto.randomUUID(), content })","handlingStrategy":"validation","validationCode":"function assertCreateMessageEvent(event) {\n  if (event.messageId == null) throw new Error('Refusing to dispatch CreateMessageEvent without messageId')\n  if (!event.cardId) throw new Error('CreateMessageEvent requires cardId')\n}","typeGuard":"function hasMessageId(e: CreateMessageEvent): e is CreateMessageEvent & { messageId: MessageID } {\n  return e.messageId != null\n}","tryCatchPattern":"try {\n  await storage.processEvent(enrichedEvent)\n} catch (e) {\n  if (e.message === 'Message id is required') {\n    console.error('Producer bug: CreateMessageEvent missing messageId', enrichedEvent)\n  }\n  throw e\n}","preventionTips":["Always assign messageId (e.g. crypto.randomUUID()) at event creation time.","Validate events at the ingestion boundary before routing to middleware.","Watch for JSON serialization dropping undefined messageId fields.","Keep producer and server event schemas in sync."],"tags":["validation","messages","events","server"],"backgroundTag":"missing-required-field","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}