mem0ai/mem0 · error · NodeOperationError

Invalid JSON in "Metadata" field

Error message

Invalid JSON in "Metadata" field

What it means

A 400 raised by _validate_bundled_providers when the submitted config specifies an LLM provider (config['llm']['provider']) that is not in BUNDLED_LLM_PROVIDERS for this server image. The Docker image only ships the Python packages for a fixed list of providers; requesting any other provider cannot work at runtime, so the server rejects the config up front with instructions to extend the image.

Solutions

  1. Check the bundled list in the error message and switch config['llm']['provider'] to one of those (e.g. 'openai').
  2. Or build a custom image: pip install the provider's package in the Dockerfile and extend BUNDLED_LLM_PROVIDERS in server/main.py, then rebuild.
  3. Or run the server from source (pip install mem0ai[<provider>] plus the server package) instead of the prebuilt image.
  4. Verify the provider string matches exactly (lowercase, no extra spaces) what mem0 expects.

Example fix

# before
{"llm": {"provider": "anthropic", "config": {"model": "claude-3-5-sonnet"}}}

# after (image bundles openai)
{"llm": {"provider": "openai", "config": {"model": "gpt-4o-mini", "api_key": "..."}}}
Defensive patterns

Strategy: validation

Validate before calling

BUNDLED_LLM_PROVIDERS = {"openai", "azure_openai", "anthropic", "gemini"}  # mirror the image's list

def validate_llm_config(cfg: dict) -> None:
    llm = cfg.get("llm") or {}
    provider = llm.get("provider", "openai")
    if provider not in BUNDLED_LLM_PROVIDERS:
        raise ValueError(f"LLM provider '{provider}' not bundled; pick from {sorted(BUNDLED_LLM_PROVIDERS)}")

Type guard

def is_bundled_llm(provider: str, bundled: set[str]) -> bool:
    return provider in bundled

Try / catch

if resp.status_code == 400 and "not bundled" in resp.text:
    raise ConfigError(resp.json()["detail"])  # config error, not transient: do not retry

Prevention

When it happens

Trigger: POST/PUT of a config with e.g. "llm": {"provider": "anthropic"} when 'anthropic' is not in the image's BUNDLED_LLM_PROVIDERS; migrating a config from a pip-installed deployment (which could install any provider) to the prebuilt Docker image; a typo in the provider name.

Common situations: Self-hosting the official container and wanting a provider the image does not bundle; a new provider exists in mem0ai on PyPI but the Docker image predates it; copying an example config that uses a niche provider.

Understand the failure class

Related errors


AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15). Data as JSON: /api/errors/0ba09c2e963279d6. Report an issue: GitHub.

Appendix: source

Thrown at integrations/n8n-nodes-mem0/nodes/Mem0/Mem0.node.ts:426

					}
					const addFields = this.getNodeParameter('addFields', i, {}) as IDataObject;
					const body: IDataObject = {
						messages: messagesUi.map((m) => ({ role: m.role, content: m.content })),
						infer: addFields.infer !== undefined ? addFields.infer : true,
					};
					const userId = this.getNodeParameter('userId', i, '') as string;
					if (userId) body.user_id = userId;
					if (addFields.agent_id) body.agent_id = addFields.agent_id;
					if (addFields.app_id) body.app_id = addFields.app_id;
					if (addFields.run_id) body.run_id = addFields.run_id;
					if (addFields.metadata) {
						try {
							body.metadata =
								typeof addFields.metadata === 'string'
									? JSON.parse(addFields.metadata as string)
									: addFields.metadata;
						} catch {
							throw new NodeOperationError(this.getNode(), 'Invalid JSON in "Metadata" field', {
								itemIndex: i,
							});
						}
					}

					// Custom extraction controls (optional): steer what the API extracts.
					if (addFields.custom_instructions) {
						body.custom_instructions = addFields.custom_instructions;
					}
					if (addFields.custom_categories) {
						try {
							body.custom_categories =
								typeof addFields.custom_categories === 'string'
									? JSON.parse(addFields.custom_categories as string)
									: addFields.custom_categories;
						} catch {
							throw new NodeOperationError(
								this.getNode(),

View on GitHub (pinned to 001c235229)