mastra-ai/mastra · error · MastraError
OBSERVABILITY_MISSING_RECORD_ID
OBSERVABILITY_MISSING_RECORD_ID
Error message
Observability record is missing required id field '${String(idField)}' What it means
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.
Source
Thrown at packages/core/src/storage/domains/observability/inmemory.ts:195
return cursorId;
}
/**
* Upserts a record into an append-only collection keyed by an id field.
*
* If an existing record with the same id is found, it is replaced in place
* (preserving its cursor id so delta polling does not re-emit it). Otherwise
* the record is appended and a fresh cursor id is allocated.
*/
private upsertByIdField<T extends Record<string, unknown>>(
records: T[],
cursorIds: Map<T, number>,
record: T,
idField: keyof T,
): void {
const id = record[idField];
if (id == null) {
throw new MastraError({
id: 'OBSERVABILITY_MISSING_RECORD_ID',
domain: ErrorDomain.STORAGE,
category: ErrorCategory.USER,
text: `Observability record is missing required id field '${String(idField)}'`,
});
}
const existingIndex = records.findIndex(existing => existing[idField] === id);
if (existingIndex !== -1) {
const previous = records[existingIndex]!;
const cursorId = cursorIds.get(previous);
cursorIds.delete(previous);
records[existingIndex] = record;
if (cursorId !== undefined) {
cursorIds.set(record, cursorId);
}
return;
}
records.push(record);View on GitHub (pinned to 75dd419e61)
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').
Example fix
// before
await storage.createScore({ value: 0.9 }); // no id -> throws
// after
await storage.createScore({ id: crypto.randomUUID(), value: 0.9 }); Defensive patterns
Strategy: validation
Validate before calling
function requireId<T extends Record<string, unknown>>(rec: T, idField: keyof T): void {
if (rec[idField] == null) throw new Error(`Record missing required id field '${String(idField)}'`);
}
records.forEach(r => requireId(r, 'id'));
await storage.batchCreateFeedback(records); Type guard
function hasId<T extends { id?: unknown }>(r: T): r is T & { id: string | number } {
return r.id != null;
} Try / catch
try {
await storage.createScore(record);
} catch (e) {
if ((e as MastraError).id === 'OBSERVABILITY_MISSING_RECORD_ID') {
logger.error('Dropping record without id', record);
} else throw e;
} Prevention
- 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.
When it happens
Trigger: Calling batchCreateMetrics, batchCreateLogs, createScore, batchCreateScores, createFeedback, or batchCreateFeedback with a record whose id field (id/scoreId/feedbackId, etc.) is missing, null, or undefined.
Common situations: 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.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- OBSERVABILITY_INVALID_DELTA_CURSOR
- OBSERVABILITY_SPAN_ID_REQUIRED
- OBSERVABILITY_TRACE_ID_REQUIRED
- [FilesystemStorage] resourceId must not be empty.
- Related work item not found in this project.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/25e3abe9227aa69d.
Report an issue: GitHub.