mem0ai/mem0 · warning · NodeOperationError
Provide text or metadata to update
Error message
Provide text or metadata to update
What it means
DELETE /api-keys/{key_id} parses key_id as a UUID; anything that is not a valid UUID string raises 404 (not 422) from the except branch. This intentionally makes malformed IDs indistinguishable from missing keys so the endpoint does not leak which key IDs exist.
Source
Thrown at integrations/n8n-nodes-mem0/nodes/Mem0/Mem0.node.ts:550
const memoryId = this.getNodeParameter('memoryId', i) as string;
responseData = await request('GET', `/v1/memories/${encodeURIComponent(memoryId)}/`);
} else if (operation === 'update') {
const memoryId = this.getNodeParameter('memoryId', i) as string;
const body: IDataObject = {};
const text = this.getNodeParameter('text', i, '') as string;
const metadata = this.getNodeParameter('metadata', i, '') as string;
if (text) body.text = text;
if (metadata) {
try {
body.metadata = typeof metadata === 'string' ? JSON.parse(metadata) : metadata;
} catch {
throw new NodeOperationError(this.getNode(), 'Invalid JSON in "Metadata" field', {
itemIndex: i,
});
}
}
if (Object.keys(body).length === 0) {
throw new NodeOperationError(this.getNode(), 'Provide text or metadata to update', {
itemIndex: i,
});
}
responseData = await request('PUT', `/v1/memories/${encodeURIComponent(memoryId)}/`, body);
} else if (operation === 'delete') {
const memoryId = this.getNodeParameter('memoryId', i) as string;
responseData = await request('DELETE', `/v1/memories/${encodeURIComponent(memoryId)}/`);
}
const arr = Array.isArray(responseData) ? responseData : [responseData];
for (const entry of arr) {
returnData.push({ json: entry, pairedItem: { item: i } });
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ json: { error: (error as Error).message }, pairedItem: { item: i } });
continue;
}View on GitHub (pinned to 001c235229)
Solutions
- Use the id field from the POST /api-keys creation response or GET /api-keys listing (a full UUID like '3fa85f64-5717-4562-b3fc-2c963f66afa6').
- Validate client-side that key_id matches a UUID pattern before issuing the DELETE.
- If your stored id is shorter, you saved the wrong field — re-fetch the key list.
Example fix
# before
requests.delete(f"{BASE}/api-keys/{key_prefix}", headers=h) # 404
# after
keys = requests.get(f"{BASE}/api-keys", headers=h).json()
key_id = next(k["id"] for k in keys if k["label"] == "ci-bot")
requests.delete(f"{BASE}/api-keys/{key_id}", headers=h) Defensive patterns
Strategy: type-guard
Validate before calling
import uuid
def is_uuid(value: str) -> bool:
try:
uuid.UUID(value)
return True
except (TypeError, ValueError):
return False
assert is_uuid(key_id), f"key_id must be a UUID, got {key_id!r}" Type guard
def is_key_id(value: str) -> bool:
"""True when value is a valid UUID string usable as an API key id."""
try:
uuid.UUID(str(value))
return True
except (TypeError, ValueError):
return False Prevention
- Store key ids from the creation response, never prefixes or labels.
- Validate UUID format client-side before DELETE calls.
- Log which field was used so mis-ids are obvious in diagnostics.
When it happens
Trigger: Calling DELETE /api-keys/my-key, /api-keys/123, or with a truncated UUID (35 chars); passing the key prefix or the raw API key value instead of the key record's id; URL-encoding issues that mangle the UUID.
Common situations: Confusing the key's id (returned in the listing/creation response) with the key material or its prefix; hand-building the URL and dropping a character; frontend storing label instead of id.
Related errors
- (error as Error).message
- Authentication failed. Your API key may be invalid or expire
- Add requires at least one of User ID, Agent ID, Run ID, or A
- Provide at least one of User ID, Agent ID, App ID, or Run ID
- Mem0 memory event ${eventId} failed: ${reason}
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/cad85ae77d291ce0.
Report an issue: GitHub.