{"record":{"id":"80a65584c409737f","repo":"TencentCloud/TencentDB-Agent-Memory","slug":"failed-to-parse-configpath-please-add-hooks-a","errorCode":null,"errorMessage":"Failed to parse ${configPath} — please add hooks.allowConversationAccess manually","messagePattern":"Failed to parse (.+?) — please add hooks\\.allowConversationAccess manually","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"MemoryCore/src/utils/ensure-hook-policy.ts","lineNumber":233,"sourceCode":"  // Fallback: manual file write\n  manualPatch(logger);\n}\n\nfunction manualPatch(logger: Logger): void {\n  const TAG = \"[memory-tdai] [hook-policy]\";\n\n  const configPath = resolveConfigPath();\n  if (!configPath) {\n    logger.warn(`${TAG} Cannot locate openclaw.json — please add hooks.allowConversationAccess manually`);\n    return;\n  }\n\n  let parsed: Record<string, unknown>;\n  try {\n    const raw = fs.readFileSync(configPath, \"utf-8\");\n    parsed = JSON5.parse(raw);\n  } catch {\n    logger.warn(`${TAG} Failed to parse ${configPath} — please add hooks.allowConversationAccess manually`);\n    return;\n  }\n\n  if (hasPolicyAlready(parsed)) return;\n\n  if (\"$include\" in parsed || (isObj(parsed.plugins) && \"$include\" in parsed.plugins)) {\n    logger.warn(`${TAG} Config uses $include — please add manually: plugins.entries.${PLUGIN_ID}.hooks.allowConversationAccess = true`);\n    return;\n  }\n\n  if (!isObj(parsed.plugins)) parsed.plugins = {};\n  const plugins = parsed.plugins as Record<string, unknown>;\n  if (!isObj(plugins.entries)) plugins.entries = {};\n  const entries = plugins.entries as Record<string, unknown>;\n  if (!isObj(entries[PLUGIN_ID])) entries[PLUGIN_ID] = {};\n  const entry = entries[PLUGIN_ID] as Record<string, unknown>;\n  if (!isObj(entry.hooks)) entry.hooks = {};\n  (entry.hooks as Record<string, unknown>).allowConversationAccess = true;","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/3efcd317b84146d6a08518ac0f7ee7c8a8d200ec/MemoryCore/src/utils/ensure-hook-policy.ts#L215-L251","documentation":"manualPatch in ensure-hook-policy.ts reads the plugin config file and tries to parse it with JSON5 before injecting the hooks.allowConversationAccess policy. When the file cannot be read or parsed (malformed JSON/JSON5 syntax), it logs this warning and returns without modifying anything, deferring the fix to the developer. The library refuses to rewrite a config it cannot parse, since a blind rewrite could destroy user data.","triggerScenarios":"Calling ensurePluginHookPolicy when configPath contains invalid JSON5 (trailing commas beyond JSON5 rules, unquoted keys, truncated file), the file does not exist, or has encoding/read permission problems — the readFileSync or JSON5.parse throws and the catch block emits the warning.","commonSituations":"Hand-edited config with a syntax typo; a partially written/corrupted config after a crash; wrong configPath passed; file locked or unreadable due to permissions; user pasted JSON with an accidental BOM or stray characters.","solutions":["Open configPath and fix the JSON5 syntax error (validate with a JSON5 parser)","Confirm the file exists at configPath and the process has read access","After making the file parseable, add plugins.entries.<PLUGIN_ID>.hooks.allowConversationAccess = true yourself or rerun ensurePluginHookPolicy","If the file is corrupted beyond repair, restore it from backup or regenerate it, then re-run the policy check"],"exampleFix":"// before (config.json)\n{\n  \"plugins\": { \"entries\": { \"my-plugin\": { },, } }\n}\n// after\n{\n  \"plugins\": {\n    \"entries\": {\n      \"my-plugin\": { \"hooks\": { \"allowConversationAccess\": true } }\n    }\n  }\n}","handlingStrategy":"fallback","validationCode":"function canParseConfig(configPath: string): boolean {\n  try { JSON5.parse(fs.readFileSync(configPath, 'utf-8')); return true; } catch { return false; }\n}","typeGuard":"function isParseableConfigFile(path: string): path is string {\n  try { JSON5.parse(fs.readFileSync(path, 'utf-8')); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  ensurePluginHookPolicy(configPath);\n} catch (err) {\n  logger.warn(`Could not apply hook policy to ${configPath}; fix the config manually`, { err });\n}","preventionTips":["Validate the config with a JSON5 parser after each manual edit","Keep the config in version control to detect corruption early","Verify file permissions and that configPath points to the real config"],"tags":["config","json5","parse-error","file-io"],"backgroundTag":"config-parse-failed","analyzedSha":"3efcd317b84146d6a08518ac0f7ee7c8a8d200ec","analyzedAt":"2026-09-01T05:44:22.276Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}