{"record":{"id":"d1dc14f516e718fa","repo":"mem0ai/mem0","slug":"invalid-json-in-custom-categories-field","errorCode":null,"errorMessage":"Invalid JSON in \"Custom Categories\" field","messagePattern":"Invalid JSON in \"Custom Categories\" field","errorType":"exception","errorClass":"NodeOperationError","httpStatus":null,"severity":"error","filePath":"integrations/n8n-nodes-mem0/nodes/Mem0/Mem0.node.ts","lineNumber":443,"sourceCode":"\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tthrow new NodeOperationError(this.getNode(), 'Invalid JSON in \"Metadata\" field', {\n\t\t\t\t\t\t\t\titemIndex: i,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Custom extraction controls (optional): steer what the API extracts.\n\t\t\t\t\tif (addFields.custom_instructions) {\n\t\t\t\t\t\tbody.custom_instructions = addFields.custom_instructions;\n\t\t\t\t\t}\n\t\t\t\t\tif (addFields.custom_categories) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tbody.custom_categories =\n\t\t\t\t\t\t\t\ttypeof addFields.custom_categories === 'string'\n\t\t\t\t\t\t\t\t\t? JSON.parse(addFields.custom_categories as string)\n\t\t\t\t\t\t\t\t\t: addFields.custom_categories;\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tthrow new NodeOperationError(\n\t\t\t\t\t\t\t\tthis.getNode(),\n\t\t\t\t\t\t\t\t'Invalid JSON in \"Custom Categories\" field',\n\t\t\t\t\t\t\t\t{ itemIndex: i },\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (addFields.includes) body.includes = addFields.includes;\n\t\t\t\t\tif (addFields.excludes) body.excludes = addFields.excludes;\n\n\t\t\t\t\t// API requires at least one entity id — fail clearly instead of a raw 4xx.\n\t\t\t\t\tif (!body.user_id && !body.agent_id && !body.run_id && !body.app_id) {\n\t\t\t\t\t\tthrow new NodeOperationError(\n\t\t\t\t\t\t\tthis.getNode(),\n\t\t\t\t\t\t\t'Add requires at least one of User ID, Agent ID, Run ID, or App ID',\n\t\t\t\t\t\t\t{ itemIndex: i },\n\t\t\t\t\t\t);\n\t\t\t\t\t}","sourceCodeStart":425,"sourceCodeEnd":461,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/integrations/n8n-nodes-mem0/nodes/Mem0/Mem0.node.ts#L425-L461","documentation":"A 400 raised by _validate_bundled_providers when config['embedder']['provider'] is set to an embedder not included in BUNDLED_EMBEDDER_PROVIDERS for this server image. Same packaging rationale as the LLM variant: the image bundles only a fixed set of embedding provider packages, and an unbundleable provider is rejected before it can produce a runtime ImportError deep inside a memory operation.","triggerScenarios":"Submitting a config with \"embedder\": {\"provider\": \"huggingface\"} when the image only bundles e.g. openai; changing embedding providers on an existing deployment without rebuilding the image; typos in the provider field.","commonSituations":"Switching from OpenAI embeddings to a local/HuggingFace embedder in the containerized server; following a docs example whose provider isn't in the shipped image; image version older than the provider you want.","solutions":["Use an embedder from the bundled list shown in the error message (commonly 'openai').","Build a custom image installing the embedder's package and extend BUNDLED_EMBEDDER_PROVIDERS in server/main.py.","Or run from source with the needed extras installed.","Double-check the provider string against mem0's supported embedder names."],"exampleFix":"# before\n{\"embedder\": {\"provider\": \"huggingface\", \"config\": {\"model\": \"BAAI/bge-small-en-v1.5\"}}}\n\n# after\n{\"embedder\": {\"provider\": \"openai\", \"config\": {\"model\": \"text-embedding-3-small\"}}}","handlingStrategy":"validation","validationCode":"BUNDLED_EMBEDDER_PROVIDERS = {\"openai\"}  # mirror the image's list\n\ndef validate_embedder_config(cfg: dict) -> None:\n    emb = cfg.get(\"embedder\") or {}\n    provider = emb.get(\"provider\", \"openai\")\n    if provider not in BUNDLED_EMBEDDER_PROVIDERS:\n        raise ValueError(f\"Embedder '{provider}' not bundled; pick from {sorted(BUNDLED_EMBEDDER_PROVIDERS)}\")","typeGuard":"def is_bundled_embedder(provider: str, bundled: set[str]) -> bool:\n    return provider in bundled","tryCatchPattern":"if resp.status_code == 400 and \"not bundled\" in resp.text:\n    raise ConfigError(resp.json()[\"detail\"])  # fix config or image; retrying unchanged will fail again","preventionTips":["Note that changing embedders invalidates existing vector dimensions — plan a re-embed.","Keep LLM and embedder allowlists in shared deployment config.","Test config submissions against the actual image, not a source checkout."],"tags":["configuration","embedder","docker","http-400","rest-server"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}