{"record":{"id":"99bf501a8861555c","repo":"rtk-ai/rtk","slug":"just-created-json-object","errorCode":null,"errorMessage":"just-created json object","messagePattern":"just-created json object","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"info","filePath":"src/hooks/init.rs","lineNumber":1383,"sourceCode":"            let keep = blank_count.min(2);\n            result.extend(std::iter::repeat_n(\"\", keep));\n        } else {\n            result.push(line);\n            i += 1;\n        }\n    }\n\n    result.join(\"\\n\")\n}\n\n/// Deep-merge RTK hook entry into settings.json\n/// Creates hooks.PreToolUse structure if missing, preserves existing hooks\nfn insert_hook_entry(root: &mut serde_json::Value, hook_command: &str) -> Result<()> {\n    let root_obj = match root.as_object_mut() {\n        Some(obj) => obj,\n        None => {\n            *root = serde_json::json!({});\n            root.as_object_mut().expect(\"just-created json object\")\n        }\n    };\n\n    let hooks = root_obj\n        .entry(\"hooks\")\n        .or_insert_with(|| serde_json::json!({}))\n        .as_object_mut()\n        .context(\"hooks value is not an object\")?;\n\n    let pre_tool_use = hooks\n        .entry(PRE_TOOL_USE_KEY)\n        .or_insert_with(|| serde_json::json!([]))\n        .as_array_mut()\n        .context(\"PreToolUse value is not an array\")?;\n\n    pre_tool_use.push(serde_json::json!({\n        \"matcher\": \"Bash\",\n        \"hooks\": [{","sourceCodeStart":1365,"sourceCodeEnd":1401,"githubUrl":"https://github.com/rtk-ai/rtk/blob/0924356b4caba4989607227b7c8824d3d8098719/src/hooks/init.rs#L1365-L1401","documentation":"This .expect() in insert_hook_entry (src/hooks/init.rs) re-borrows root.as_object_mut() immediately after replacing *root with serde_json::json!({}). The fresh value is guaranteed to be an object, so the expect can never fire; it exists to convert Option<&mut Map> into a reference without error plumbing. It is an internal invariant assertion inside rtk's hook installer, hit only if the code's own logic were broken.","triggerScenarios":"Calling insert_hook_entry with a non-object root (e.g. null or an array): the function overwrites it with {} and then unwraps — the panic path is unreachable in correct builds but is the designated crash point if the invariant ever breaks.","commonSituations":"Users do not trigger this directly; it can only surface from a bug in rtk's init code or from fuzzing/dynamic misuse of the internal function via patch_settings_json_command or tests.","solutions":["Update/reinstall rtk — if you actually see this panic, report it with the settings.json content as a bug","Inspect the JSON file being patched (settings.json / codex hooks json); a non-object root is replaced automatically, so no user fix is needed","Work around by ensuring the target hook file's root is a JSON object before running `rtk init`"],"exampleFix":"// before\n*root = serde_json::json!({});\nroot.as_object_mut().expect(\"just-created json object\")\n// after (panic-free variant)\n*root = serde_json::json!({});\nroot.as_object_mut().ok_or_else(|| anyhow::anyhow!(\"root is not a JSON object\"))?","handlingStrategy":"type-guard","validationCode":"// Caller-side: ensure the settings root is a JSON object before init patches it\nif !value.is_object() {\n    value = serde_json::json!({});\n}","typeGuard":"fn is_json_object(v: &serde_json::Value) -> bool { v.is_object() }","tryCatchPattern":"// Panics are not catchable in Rust; treat any occurrence as a bug\nmatch std::panic::catch_unwind(|| rtk_init_patch()) {\n    Ok(_) => {},\n    Err(_) => eprintln!(\"rtk init invariant violated — file a bug\"),\n}","preventionTips":["Keep settings.json/hook files as JSON objects at the root","Validate JSON files after manual edits before running `rtk init`","Report any 'just-created json object' panic upstream with the file content","Keep rtk updated to pick up invariant fixes"],"tags":["rust","serde-json","panic","internal-invariant","hooks"],"backgroundTag":"internal-invariant-violation","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"}