{"record":{"id":"7a4dbfb606dfd749","repo":"thedotmack/claude-mem","slug":"invalid-response","errorCode":"invalid_response","errorMessage":"sessionId is required for endSession","messagePattern":"sessionId is required for endSession","errorType":"error_code","errorClass":"ServerClientError","httpStatus":null,"severity":"error","filePath":"src/services/hooks/server-client.ts","lineNumber":222,"sourceCode":"    this.baseUrl = stripTrailingSlash(config.serverBaseUrl);\n    this.apiKey = config.apiKey;\n    this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n  }\n\n  async startSession(input: ServerStartSessionRequest): Promise<ServerStartSessionResponse> {\n    const body = this.buildStartSessionPayload(input);\n    return this.request<ServerStartSessionResponse>('POST', '/v1/sessions/start', body);\n  }\n\n  async recordEvent(input: ServerRecordEventRequest): Promise<ServerRecordEventResponse> {\n    const body = this.buildEventPayload(input);\n    const path = input.generate === false ? '/v1/events?generate=false' : '/v1/events';\n    return this.request<ServerRecordEventResponse>('POST', path, body);\n  }\n\n  async endSession(input: ServerEndSessionRequest): Promise<ServerEndSessionResponse> {\n    if (!input.sessionId) {\n      throw new ServerClientError('invalid_response', 'sessionId is required for endSession');\n    }\n    return this.request<ServerEndSessionResponse>(\n      'POST',\n      `/v1/sessions/${encodeURIComponent(input.sessionId)}/end`,\n      {},\n    );\n  }\n\n  // Phase 8 — direct observation insert (MCP `observation_add`). Calls\n  // `/v1/memories`, which is the canonical write path that MUST NOT enqueue\n  // a generation job. Anti-pattern guard for plan line 770: never duplicate\n  // generation logic in MCP tools.\n  async addObservation(\n    input: ServerAddObservationRequest,\n  ): Promise<ServerAddObservationResponse> {\n    return this.request<ServerAddObservationResponse>(\n      'POST',\n      '/v1/memories',","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/src/services/hooks/server-client.ts#L204-L240","documentation":"Thrown by ServerClient.endSession() when input.sessionId is falsy. The kind is 'invalid_response' (a client-side guard, despite the name) and fires before the POST /v1/sessions/<id>/end request is built, so no network call occurs on failure.","triggerScenarios":"Calling endSession({ sessionId: '' }), endSession({}) (sessionId undefined), or with a null/whitespace id. The guard is a simple truthiness check on input.sessionId.","commonSituations":"Hook handler tries to end a session that was never started (no start response captured); sessionId variable was undefined after a failed startSession; caller passes the whole start response object instead of its id field.","solutions":["Capture and pass the sessionId returned by startSession() into endSession().","Guard the end call: only invoke endSession when you have a non-empty sessionId.","If session start failed, skip the end call entirely rather than passing an empty id."],"exampleFix":"// before\nawait client.endSession({ sessionId: '' });\n// throws ServerClientError(invalid_response, 'sessionId is required for endSession')\n\n// after\nconst { sessionId } = await client.startSession({ ... });\n// ... later, only if we got one\nif (sessionId) {\n  await client.endSession({ sessionId });\n}","handlingStrategy":"validation","validationCode":"if (!input?.sessionId) {\n  throw new Error('endSession: sessionId is required (capture it from startSession)');\n}","typeGuard":"function hasSessionId(input: unknown): input is { sessionId: string } {\n  return typeof (input as any)?.sessionId === 'string' && (input as any).sessionId.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Capture and propagate the sessionId from startSession to endSession.","Skip the end call when start failed rather than passing an empty id.","Pass the id string, not the whole start response object."],"tags":["server-mode","validation","sessions","server-client"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}