fix(ts-oss): coerce non-string entity ids instead of crashing on trim() (#6263)

Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
This commit is contained in:
Abhay Singh
2026-07-21 12:48:15 +05:30
committed by GitHub
co-authored by kartik-mem0
parent c2bc28e589
commit 39551145b8
2 changed files with 33 additions and 4 deletions
+5 -4
View File
@@ -126,18 +126,19 @@ function rejectTopLevelEntityParams(
/** /**
* Validates and normalizes an entity ID. * Validates and normalizes an entity ID.
* - Coerces non-string ids (e.g. numeric database keys) to string
* - Trims leading/trailing whitespace * - Trims leading/trailing whitespace
* - Rejects empty or whitespace-only strings * - Rejects empty or whitespace-only strings
* - Rejects strings containing internal whitespace * - 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 * @throws Error if entity ID is invalid
*/ */
function validateAndTrimEntityId( function validateAndTrimEntityId(
value: string | undefined, value: string | number | undefined | null,
name: string, name: string,
): string | undefined { ): string | undefined {
if (value === undefined) return undefined; if (value == null) return undefined;
const trimmed = value.trim(); const trimmed = String(value).trim();
if (trimmed === "") { if (trimmed === "") {
throw new Error( throw new Error(
`Invalid ${name}: cannot be empty or whitespace-only. Provide a valid identifier.`, `Invalid ${name}: cannot be empty or whitespace-only. Provide a valid identifier.`,
@@ -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<string, any>;
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<string, any>;
expect(passedFilters.user_id).toBe("42");
searchSpy.mockRestore();
});
});
describe("search() filter entity ID validation", () => { describe("search() filter entity ID validation", () => {
it("should throw error when user_id in filters is whitespace-only", async () => { it("should throw error when user_id in filters is whitespace-only", async () => {
await expect( await expect(