Skip to content

observation_add / memory_add fail with 400 in server-beta mode #2987

Description

@arclabch

Before submitting


📝 Manual Bug Report

Bug Description

observation_add and memory_add MCP tools always fail with a 400 ValidationError in server-beta mode. The content field is provided by the caller but arrives as undefined at the server.

Server beta POST /v1/memories returned 400:
{"error":"ValidationError","issues":[{"expected":"string","code":"invalid_type","path":["content"],"message":"Invalid input: expected string, received undefined"}]}

Root cause: In mcp-server.cjs, the buildAddObservationPayload method in the ServerBetaClient class maps the content value to the legacy field name narrative instead of content:

buildAddObservationPayload(e) {
  let r = e.content,           // ← reads content correctly
      n = e.kind ?? "manual",
      ...
  return {
    projectId: e.projectId,
    kind: n,
    type: n,
    narrative: r,              // ← BUG: should be `content: r`
    ...
  }
}

The server-beta POST /v1/memories endpoint expects content, not narrative. The field narrative is the legacy worker-mode name and was not updated when the server-beta payload builder was written.

Read operations (observation_search, get_observations, timeline) are unaffected — they use a separate buildSearchPayload method that doesn't touch the content/narrative field.

Steps to Reproduce

  1. Configure claude-mem in server-beta mode (PostgreSQL + Valkey/BullMQ)
  2. Call the observation_add MCP tool with a content parameter
  3. Receive 400 ValidationError — content is undefined
  4. Same result with memory_add (and its narrative legacy alias)

Expected Behavior

The observation should be created and returned with the provided content.

Environment

  • Claude-mem version: 13.6.1 (latest on npm)
  • Claude Code version: 2.1.179
  • OS: Linux 6.12.90+deb13.1-amd64 x86_64
  • Platform: Debian 13, server-beta mode with PostgreSQL + Valkey

Logs

The 400 error is surfaced client-side in the MCP tool result, not in the worker log. Worker log shows no corresponding error for these calls — the request is rejected by the server-beta HTTP layer before reaching the queue.

Server beta POST /v1/memories returned 400:
{"error":"ValidationError","issues":[{"expected":"string","code":"invalid_type","path":["content"],"message":"Invalid input: expected string, received undefined"}]}

Additional Context

  • Fix confirmed locally: changing narrative: r to content: r in buildAddObservationPayload resolves the issue — write-read round-trip verified after patching and restarting the session.
  • Only the write path is affected. All read/search tools work correctly.
  • The memory_add compatibility alias constructs content from t?.content ?? t?.narrative ?? "" then feeds it into the same broken buildAddObservationPayload, so it fails identically.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed bug

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions