{"record":{"id":"2f69bc4bfbaf703f","repo":"thedotmack/claude-mem","slug":"observation-record-event-eventtype-is-required","errorCode":null,"errorMessage":"observation_record_event: \"eventType\" is required","messagePattern":"observation_record_event: \"eventType\" is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/servers/mcp-server.ts","lineNumber":282,"sourceCode":"  serverSessionId?: string | null;\n  contentSessionId?: string | null;\n  memorySessionId?: string | null;\n  platformSource?: string | null;\n  sourceType?: 'hook' | 'worker' | 'provider' | 'server' | 'api';\n  eventType: string;\n  payload?: unknown;\n  occurredAtEpoch?: number;\n  generate?: boolean;\n}\n\nfunction normalizeMcpPlatformSource(value: string | null): string | null {\n  return typeof value === 'string' ? normalizePlatformSource(value) : null;\n}\n\nconst handleObservationRecordEvent = wrapHandler('observation_record_event', async (args: ObservationRecordEventArgs) => {\n  const ctx = requireServerForObservationTool('observation_record_event');\n  if (typeof args?.eventType !== 'string' || args.eventType.trim().length === 0) {\n    throw new Error('observation_record_event: \"eventType\" is required');\n  }\n  const projectId = args.projectId && args.projectId.trim().length > 0 ? args.projectId : ctx.projectId;\n  const request: ServerRecordEventRequest = {\n    projectId,\n    sourceType: args.sourceType ?? 'api',\n    eventType: args.eventType,\n    occurredAtEpoch: typeof args.occurredAtEpoch === 'number' ? args.occurredAtEpoch : Date.now(),\n    ...(args.serverSessionId !== undefined ? { serverSessionId: args.serverSessionId } : {}),\n    ...(args.contentSessionId !== undefined ? { contentSessionId: args.contentSessionId } : {}),\n    ...(args.memorySessionId !== undefined ? { memorySessionId: args.memorySessionId } : {}),\n    ...(args.platformSource !== undefined ? { platformSource: normalizeMcpPlatformSource(args.platformSource) } : {}),\n    ...(args.payload !== undefined ? { payload: args.payload } : {}),\n    ...(args.generate !== undefined ? { generate: args.generate } : {}),\n  };\n  const response = await ctx.client.recordEvent(request);\n  return formatJsonResult(response);\n});\n","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/servers/mcp-server.ts#L264-L300","documentation":"The observation_record_event MCP tool handler validates its arguments before forwarding them to the server. It throws this error when the 'eventType' argument is absent, not a string, or an empty/whitespace-only string. The library enforces this so events recorded via the observation pipeline always carry a valid event type.","triggerScenarios":"Calling the observation_record_event tool with args missing 'eventType', with eventType set to null/undefined, a non-string value, or a string like '' or '   ' (the handler checks typeof === 'string' && trim().length > 0).","commonSituations":"LLM clients invoking the tool without the eventType parameter; tool-call argument serialization dropping optional-looking fields; renaming eventType to type/event_type in caller code; template-generated calls where the variable was empty.","solutions":["Pass a non-empty string eventType, e.g. { eventType: 'user_prompt_submitted' }","If the value comes from a variable, default it before calling: args.eventType?.trim() || fallbackEventType","Check the tool's input schema (required: eventType) in the MCP client to catch it at call-construction time","Ensure the caller is not passing snake_case job-style aliases; unlike jobId there is no fallback name for eventType"],"exampleFix":"// before\nawait callTool('observation_record_event', { projectId: 'p1', sourceType: 'api' });\n// after\nawait callTool('observation_record_event', { projectId: 'p1', sourceType: 'api', eventType: 'tool_call_completed' });","handlingStrategy":"validation","validationCode":"function canRecordEvent(args) {\n  return typeof args?.eventType === 'string' && args.eventType.trim().length > 0;\n}\nif (!canRecordEvent(args)) throw new Error('eventType must be a non-empty string before calling observation_record_event');","typeGuard":"function hasEventType(args: unknown): args is { eventType: string } & Record<string, unknown> {\n  return typeof (args as any)?.eventType === 'string' && (args as any).eventType.trim().length > 0;\n}","tryCatchPattern":"try {\n  return await callTool('observation_record_event', args);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('\"eventType\" is required')) {\n    console.error('Provide a non-empty eventType, e.g. tool_call_completed');\n    return null;\n  }\n  throw e;\n}","preventionTips":["Always supply a non-empty eventType constant from your event vocabulary","Validate tool args against the MCP input schema before dispatch","Never pass user-controlled strings without trimming/emptiness checks","Keep eventType key spelling consistent (camelCase, not event_type)"],"tags":["mcp","validation","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}