{"record":{"id":"2c72f2a0d79a022c","repo":"rtk-ai/rtk","slug":"trae-hooks-value-is-not-an-object","errorCode":null,"errorMessage":"Trae hooks value is not an object","messagePattern":"Trae hooks value is not an object","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/hooks/init.rs","lineNumber":5102,"sourceCode":"        None => Ok((serde_json::json!({ \"version\": 1 }), false)),\n    }\n}\n\nfn validate_trae_hooks_json(root: &serde_json::Value) -> Result<()> {\n    let root_object = root\n        .as_object()\n        .context(\"Trae hooks.json root must be an object\")?;\n    if root_object\n        .get(\"version\")\n        .is_some_and(|version| version != &serde_json::json!(1))\n    {\n        anyhow::bail!(\"Trae hooks.json version must be 1\");\n    }\n    if root_object\n        .get(\"hooks\")\n        .is_some_and(|hooks| !hooks.is_object())\n    {\n        anyhow::bail!(\"Trae hooks value is not an object\");\n    }\n    if root_object\n        .get(\"hooks\")\n        .and_then(|hooks| hooks.get(PRE_TOOL_USE_KEY))\n        .is_some_and(|pre_tool_use| !pre_tool_use.is_array())\n    {\n        anyhow::bail!(\"Trae PreToolUse value is not an array\");\n    }\n    Ok(())\n}\n\n/// Install RTK's Trae hook in every supplied target. All targets are read and\n/// parsed before any write, so malformed `.trae` or `.trae-cn` configuration\n/// cannot cause a partially-applied update.\nfn patch_trae_hooks_json_paths(paths: &[PathBuf], ctx: InitContext) -> Result<Vec<PatchResult>> {\n    struct PendingPatch {\n        path: PathBuf,\n        existed: bool,","sourceCodeStart":5084,"sourceCodeEnd":5120,"githubUrl":"https://github.com/rtk-ai/rtk/blob/0924356b4caba4989607227b7c8824d3d8098719/src/hooks/init.rs#L5084-L5120","documentation":"During Trae hooks.json validation, if a `hooks` key is present it must be a JSON object mapping hook events to their entries. If `hooks` exists but is an array, string, number, etc., rtk bails because it cannot merge RTK's PreToolUse hook into a malformed structure.","triggerScenarios":"Running `rtk init` for Trae where the existing `.trae/hooks.json` (or `.trae-cn`) parses as JSON and has a `hooks` field whose value is not an object (e.g. an array or string).","commonSituations":"Manual editing mistakes (bracket slipped, `hooks` written as a list); another tool generated an incompatible layout; copy-paste corruption of the config.","solutions":["Edit hooks.json so `hooks` is an object, e.g. `{\"version\":1,\"hooks\":{}}`.","Compare against a working Trae hooks.json from another project and fix the structure.","Back up and reset the file to the minimal valid skeleton, then rerun `rtk init` to let rtk write the hook."],"exampleFix":"// before (.trae/hooks.json)\n{ \"version\": 1, \"hooks\": [] }\n// after\n{ \"version\": 1, \"hooks\": {} }","handlingStrategy":"validation","validationCode":"const fs = require('fs');\nfunction hooksIsObject(p = '.trae/hooks.json') {\n  if (!fs.existsSync(p)) return true;\n  const j = JSON.parse(fs.readFileSync(p, 'utf8'));\n  return j.hooks === undefined || (typeof j.hooks === 'object' && !Array.isArray(j.hooks));\n}","typeGuard":"const hooksOk = (j) => j.hooks === undefined || (typeof j.hooks === 'object' && j.hooks !== null && !Array.isArray(j.hooks));","tryCatchPattern":"match rtk init result { Err if msg contains 'hooks value is not an object' => restructure hooks as an object and retry }","preventionTips":["Validate hooks.json with a JSON schema before committing it.","Keep `hooks` a map of event names to entries, never a list.","Copy hook configs from known-good Trae projects only."],"tags":["json","schema-validation","trae","hooks"],"backgroundTag":"schema-validation-failed","analyzedSha":"0924356b4caba4989607227b7c8824d3d8098719","analyzedAt":"2026-09-19T19:25:29.612Z","contentChangedAt":"2026-09-19T19:25:29.612Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}