{"record":{"id":"25e3abe9227aa69d","repo":"mastra-ai/mastra","slug":"observability-missing-record-id","errorCode":"OBSERVABILITY_MISSING_RECORD_ID","errorMessage":"Observability record is missing required id field '${String(idField)}'","messagePattern":"Observability record is missing required id field '(.+?)'","errorType":"error_code","errorClass":"MastraError","httpStatus":null,"severity":"error","filePath":"packages/core/src/storage/domains/observability/inmemory.ts","lineNumber":195,"sourceCode":"    return cursorId;\n  }\n\n  /**\n   * Upserts a record into an append-only collection keyed by an id field.\n   *\n   * If an existing record with the same id is found, it is replaced in place\n   * (preserving its cursor id so delta polling does not re-emit it). Otherwise\n   * the record is appended and a fresh cursor id is allocated.\n   */\n  private upsertByIdField<T extends Record<string, unknown>>(\n    records: T[],\n    cursorIds: Map<T, number>,\n    record: T,\n    idField: keyof T,\n  ): void {\n    const id = record[idField];\n    if (id == null) {\n      throw new MastraError({\n        id: 'OBSERVABILITY_MISSING_RECORD_ID',\n        domain: ErrorDomain.STORAGE,\n        category: ErrorCategory.USER,\n        text: `Observability record is missing required id field '${String(idField)}'`,\n      });\n    }\n    const existingIndex = records.findIndex(existing => existing[idField] === id);\n    if (existingIndex !== -1) {\n      const previous = records[existingIndex]!;\n      const cursorId = cursorIds.get(previous);\n      cursorIds.delete(previous);\n      records[existingIndex] = record;\n      if (cursorId !== undefined) {\n        cursorIds.set(record, cursorId);\n      }\n      return;\n    }\n    records.push(record);","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/storage/domains/observability/inmemory.ts#L177-L213","documentation":"upsertByIdField indexes observability records (metrics, logs, scores, feedback) by a required id field to maintain delta cursors. If the record's id field is null or undefined, this USER-category error is thrown because such a record cannot be inserted or tracked.","triggerScenarios":"Calling batchCreateMetrics, batchCreateLogs, createScore, batchCreateScores, createFeedback, or batchCreateFeedback with a record whose id field (id/scoreId/feedbackId, etc.) is missing, null, or undefined.","commonSituations":"Deserializing records from JSON/CSV where the id column was dropped; constructing records programmatically and forgetting the id; a producer emitting telemetry events without ids; schema changes renaming the id field.","solutions":["Ensure every record passed to the batch/create methods has its id field populated before calling.","Add upstream validation at the producer/client boundary that rejects records lacking ids.","Generate ids at creation time (crypto.randomUUID()) when records are synthesized in code.","Check for field renames between serialization and insertion (e.g. mapping 'key' to 'id')."],"exampleFix":"// before\nawait storage.createScore({ value: 0.9 }); // no id -> throws\n\n// after\nawait storage.createScore({ id: crypto.randomUUID(), value: 0.9 });","handlingStrategy":"validation","validationCode":"function requireId<T extends Record<string, unknown>>(rec: T, idField: keyof T): void {\n  if (rec[idField] == null) throw new Error(`Record missing required id field '${String(idField)}'`);\n}\nrecords.forEach(r => requireId(r, 'id'));\nawait storage.batchCreateFeedback(records);","typeGuard":"function hasId<T extends { id?: unknown }>(r: T): r is T & { id: string | number } {\n  return r.id != null;\n}","tryCatchPattern":"try {\n  await storage.createScore(record);\n} catch (e) {\n  if ((e as MastraError).id === 'OBSERVABILITY_MISSING_RECORD_ID') {\n    logger.error('Dropping record without id', record);\n  } else throw e;\n}","preventionTips":["Validate id presence at the producer boundary before records enter storage queues.","Always generate ids (crypto.randomUUID()) when synthesizing records in code.","Check serialization/mapping code for dropped or renamed id fields.","Add schema validation (zod) requiring id on observability payloads."],"tags":["storage","observability","validation","missing-id"],"backgroundTag":"missing-required-field","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}