{"record":{"id":"df9881cf4a6f457f","repo":"mem0ai/mem0","slug":"openclaw-mem0-config-required","errorCode":null,"errorMessage":"openclaw-mem0 config required","messagePattern":"openclaw-mem0 config required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"integrations/openclaw/config.ts","lineNumber":178,"sourceCode":"  \"topK\",\n  \"oss\",\n  \"skills\",\n];\n\nfunction assertAllowedKeys(\n  value: Record<string, unknown>,\n  allowed: string[],\n  label: string,\n) {\n  const unknown = Object.keys(value).filter((key) => !allowed.includes(key));\n  if (unknown.length === 0) return;\n  throw new Error(`${label} has unknown keys: ${unknown.join(\", \")}`);\n}\n\nexport const mem0ConfigSchema = {\n  parse(value: unknown, fileConfig?: FileConfig): Mem0Config {\n    if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n      throw new Error(\"openclaw-mem0 config required\");\n    }\n    const cfg = value as Record<string, unknown>;\n    assertAllowedKeys(cfg, ALLOWED_KEYS, \"openclaw-mem0 config\");\n\n    // Only two modes: \"platform\" (default) or \"open-source\"\n    if (\n      typeof cfg.mode === \"string\" &&\n      cfg.mode !== \"platform\" &&\n      cfg.mode !== \"open-source\"\n    ) {\n      console.warn(\n        `[mem0] Unknown mode \"${cfg.mode}\" — expected \"platform\" or \"open-source\". Defaulting to \"platform\".`,\n      );\n    }\n    const mode: Mem0Mode =\n      cfg.mode === \"open-source\" ? \"open-source\" : \"platform\";\n\n    // Resolve API key: pluginConfig → fileConfig fallback (from openclaw.json plugin section)","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/integrations/openclaw/config.ts#L160-L196","documentation":"Thrown by mem0ConfigSchema.parse when the plugin config value passed to register() is missing, null, a primitive, or an array — parse requires a plain object to validate keys against. Note the plugin's config must at least be an object ({} is fine); the gateway resolves ${VAR} substitution before calling parse, so this is a structural failure, not a missing-variable failure.","triggerScenarios":"Registering the plugin with pluginConfig = null/undefined/'platform'/[]; a gateway or host that passes the raw JSON file content when it is an array; test harnesses calling parse(0) or parse('string').","commonSituations":"Host integration (OpenClaw gateway) miswired and passing the wrong slice of openclaw.json; plugin loaded with an empty plugins section that evaluates to undefined; version mismatch between gateway contract and plugin expectations.","solutions":["Ensure the plugins['openclaw-mem0'] section in openclaw.json exists and is a JSON object — even {} passes.","If hosting the plugin yourself, pass an object (not JSON string) to register/parse; JSON.parse first if you hold a string.","After editing, re-run a config command to confirm parsing succeeds before starting the gateway."],"exampleFix":"// before\nregister({ pluginConfig: JSON.stringify(cfg) }); // string fails\n\n// after\nregister({ pluginConfig: cfg }); // plain object","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function isPluginConfig(v: unknown): v is Record<string, unknown> {\n  return typeof v === 'object' && v !== null && !Array.isArray(v);\n}","tryCatchPattern":"try {\n  mem0ConfigSchema.parse(pluginConfig);\n} catch (err) {\n  if ((err as Error).message === 'openclaw-mem0 config required') {\n    // host passed wrong shape: ensure plugins['openclaw-mem0'] is a JSON object\n  }\n  throw err;\n}","preventionTips":["Always define the plugins['openclaw-mem0'] section, even as {}.","Host integrations: pass a parsed object, not a JSON string or array."],"tags":["config","schema","validation","typescript"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}