thedotmack/claude-mem · error

observation_record_event: "eventType" is required

Error message

observation_record_event: "eventType" is required

What it means

Validation error inside the observation_record_event tool handler. After the server-runtime guard passes, the handler requires args.eventType to be a non-empty trimmed string and throws this plain Error if it is missing or blank. This runs before the event is sent to /v1/events, so no network call is made on failure.

Source

Thrown at src/servers/mcp-server.ts:277

  serverSessionId?: string | null;
  contentSessionId?: string | null;
  memorySessionId?: string | null;
  platformSource?: string | null;
  sourceType?: 'hook' | 'worker' | 'provider' | 'server' | 'api';
  eventType: string;
  payload?: unknown;
  occurredAtEpoch?: number;
  generate?: boolean;
}

function normalizeMcpPlatformSource(value: string | null): string | null {
  return typeof value === 'string' ? normalizePlatformSource(value) : null;
}

const handleObservationRecordEvent = wrapHandler('observation_record_event', async (args: ObservationRecordEventArgs) => {
  const ctx = requireServerForObservationTool('observation_record_event');
  if (typeof args?.eventType !== 'string' || args.eventType.trim().length === 0) {
    throw new Error('observation_record_event: "eventType" is required');
  }
  const projectId = args.projectId && args.projectId.trim().length > 0 ? args.projectId : ctx.projectId;
  const request: ServerRecordEventRequest = {
    projectId,
    sourceType: args.sourceType ?? 'api',
    eventType: args.eventType,
    occurredAtEpoch: typeof args.occurredAtEpoch === 'number' ? args.occurredAtEpoch : Date.now(),
    ...(args.serverSessionId !== undefined ? { serverSessionId: args.serverSessionId } : {}),
    ...(args.contentSessionId !== undefined ? { contentSessionId: args.contentSessionId } : {}),
    ...(args.memorySessionId !== undefined ? { memorySessionId: args.memorySessionId } : {}),
    ...(args.platformSource !== undefined ? { platformSource: normalizeMcpPlatformSource(args.platformSource) } : {}),
    ...(args.payload !== undefined ? { payload: args.payload } : {}),
    ...(args.generate !== undefined ? { generate: args.generate } : {}),
  };
  const response = await ctx.client.recordEvent(request);
  return formatJsonResult(response);
});

View on GitHub (pinned to d768ba3643)

Solutions

  1. Supply a non-empty eventType string (e.g. 'session.start', 'tool.call').
  2. If you intended to write free-text memory, use observation_add with content instead.
  3. Validate eventType is a non-empty string on the client before invoking the tool.

Example fix

// before
await tools.observation_record_event({
  sourceType: 'hook',
  payload: { tool: 'Edit' },
});
// throws 'observation_record_event: "eventType" is required'

// after
await tools.observation_record_event({
  eventType: 'tool.call',
  sourceType: 'hook',
  payload: { tool: 'Edit' },
});
Defensive patterns

Strategy: validation

Validate before calling

if (typeof args?.eventType !== 'string' || args.eventType.trim().length === 0) {
  return { content: [{ type: 'text', text: 'eventType is required' }], isError: true };
}

Type guard

function hasEventType(v: unknown): v is { eventType: string } {
  return typeof (v as any)?.eventType === 'string' && (v as any).eventType.trim().length > 0;
}

Prevention

When it happens

Trigger: Calling observation_record_event with eventType omitted, null, non-string, or whitespace-only. Common when the caller passes payload/platformSource but forgets the discriminating event type.

Common situations: Automation mirrors a hook event but forgets the eventType field; an LLM client passes { sourceType: 'hook' } only; eventType comes from a variable that was undefined; caller confused record_event (typed event) with observation_add (free content).

Related errors


AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12). Data as JSON: /api/errors/2f69bc4bfbaf703f. Report an issue: GitHub.