diff --git a/mem0-ts/src/oss/src/memory/index.ts b/mem0-ts/src/oss/src/memory/index.ts index 5ad72dd0c..d21951bb3 100644 --- a/mem0-ts/src/oss/src/memory/index.ts +++ b/mem0-ts/src/oss/src/memory/index.ts @@ -126,18 +126,19 @@ function rejectTopLevelEntityParams( /** * Validates and normalizes an entity ID. + * - Coerces non-string ids (e.g. numeric database keys) to string * - Trims leading/trailing whitespace * - Rejects empty or whitespace-only strings * - Rejects strings containing internal whitespace - * @returns The trimmed entity ID, or undefined if input is undefined + * @returns The trimmed entity ID, or undefined if input is undefined/null * @throws Error if entity ID is invalid */ function validateAndTrimEntityId( - value: string | undefined, + value: string | number | undefined | null, name: string, ): string | undefined { - if (value === undefined) return undefined; - const trimmed = value.trim(); + if (value == null) return undefined; + const trimmed = String(value).trim(); if (trimmed === "") { throw new Error( `Invalid ${name}: cannot be empty or whitespace-only. Provide a valid identifier.`, diff --git a/mem0-ts/src/oss/tests/memory.validation.test.ts b/mem0-ts/src/oss/tests/memory.validation.test.ts index 5503a8902..9efd96b6f 100644 --- a/mem0-ts/src/oss/tests/memory.validation.test.ts +++ b/mem0-ts/src/oss/tests/memory.validation.test.ts @@ -253,6 +253,34 @@ describe("Memory Input Validation", () => { }); }); + describe("non-string entity ID coercion", () => { + it("coerces an integer user_id in getAll filters to its string form", async () => { + const listSpy = jest + .spyOn((memory as any).vectorStore, "list") + .mockResolvedValue([[], 0]); + + await memory.getAll({ filters: { user_id: 42 as any } }); + + const passedFilters = listSpy.mock.calls[0][0] as Record; + expect(passedFilters.user_id).toBe("42"); + + listSpy.mockRestore(); + }); + + it("coerces an integer user_id in search filters to its string form", async () => { + const searchSpy = jest + .spyOn((memory as any).vectorStore, "search") + .mockResolvedValue([]); + + await memory.search("q", { filters: { user_id: 42 as any } }); + + const passedFilters = searchSpy.mock.calls[0][2] as Record; + expect(passedFilters.user_id).toBe("42"); + + searchSpy.mockRestore(); + }); + }); + describe("search() filter entity ID validation", () => { it("should throw error when user_id in filters is whitespace-only", async () => { await expect(