rtk-ai/rtk · info

just-created json object

Error message

just-created json object

What it means

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.

Solutions

  1. Update/reinstall rtk — if you actually see this panic, report it with the settings.json content as a bug
  2. Inspect the JSON file being patched (settings.json / codex hooks json); a non-object root is replaced automatically, so no user fix is needed
  3. Work around by ensuring the target hook file's root is a JSON object before running `rtk init`

Example fix

// before
*root = serde_json::json!({});
root.as_object_mut().expect("just-created json object")
// after (panic-free variant)
*root = serde_json::json!({});
root.as_object_mut().ok_or_else(|| anyhow::anyhow!("root is not a JSON object"))?
Defensive patterns

Strategy: type-guard

Validate before calling

// Caller-side: ensure the settings root is a JSON object before init patches it
if !value.is_object() {
    value = serde_json::json!({});
}

Type guard

fn is_json_object(v: &serde_json::Value) -> bool { v.is_object() }

Try / catch

// Panics are not catchable in Rust; treat any occurrence as a bug
match std::panic::catch_unwind(|| rtk_init_patch()) {
    Ok(_) => {},
    Err(_) => eprintln!("rtk init invariant violated — file a bug"),
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of rtk-ai/rtk@0924356b4c (2026-09-19). Data as JSON: /api/errors/99bf501a8861555c. Report an issue: GitHub.

Appendix: source

Thrown at src/hooks/init.rs:1383

            let keep = blank_count.min(2);
            result.extend(std::iter::repeat_n("", keep));
        } else {
            result.push(line);
            i += 1;
        }
    }

    result.join("\n")
}

/// Deep-merge RTK hook entry into settings.json
/// Creates hooks.PreToolUse structure if missing, preserves existing hooks
fn insert_hook_entry(root: &mut serde_json::Value, hook_command: &str) -> Result<()> {
    let root_obj = match root.as_object_mut() {
        Some(obj) => obj,
        None => {
            *root = serde_json::json!({});
            root.as_object_mut().expect("just-created json object")
        }
    };

    let hooks = root_obj
        .entry("hooks")
        .or_insert_with(|| serde_json::json!({}))
        .as_object_mut()
        .context("hooks value is not an object")?;

    let pre_tool_use = hooks
        .entry(PRE_TOOL_USE_KEY)
        .or_insert_with(|| serde_json::json!([]))
        .as_array_mut()
        .context("PreToolUse value is not an array")?;

    pre_tool_use.push(serde_json::json!({
        "matcher": "Bash",
        "hooks": [{

View on GitHub (pinned to 0924356b4c)