rtk-ai/rtk · error · anyhow::Error

Refusing to modify malformed {} at {}

Error message

Refusing to modify malformed {} at {}

What it means

write_rtk_block upserts an RTK-owned marker block into agent instruction files (CLAUDE.md, AGENTS.md, Copilot instructions, ...). If the existing content contains the opening marker '<!-- rtk-instructions' without the matching closing marker '<!-- /rtk-instructions -->', upsert_rtk_block returns Malformed and rtk refuses to write, printing the offending line number and an exact recovery command. This is a data-safety guard: auto-repair could duplicate or eat user content.

Source

Thrown at src/hooks/init.rs:2573

                println!("[ok] {} already up to date in {}", label, path.display());
            }
        }
        RtkBlockUpsert::Malformed => {
            eprintln!(
                "[warn] Found '{}' without closing marker in {}",
                RTK_BLOCK_START,
                path.display()
            );
            if let Some((line_num, _)) = existing
                .lines()
                .enumerate()
                .find(|(_, line)| line.contains(RTK_BLOCK_START))
            {
                eprintln!("    Location: line {}", line_num + 1);
            }
            eprintln!("    Action: Manually remove the incomplete block, then re-run:");
            eprintln!("            {recovery_cmd}");
            anyhow::bail!(
                "Refusing to modify malformed {} at {}",
                label,
                path.display()
            );
        }
    }

    Ok(action)
}

/// Patch CLAUDE.md: add @RTK.md, migrate if old block exists
fn patch_claude_md(path: &Path, ctx: InitContext) -> Result<bool> {
    let InitContext { verbose, dry_run } = ctx;
    let mut content = if path.exists() {
        fs::read_to_string(path)?
    } else {
        String::new()
    };

View on GitHub (pinned to d977e1c316)

Solutions

  1. Open the file at the 'Location: line N' printed just above the error and delete the entire incomplete block, from the '<!-- rtk-instructions' opening marker through where the closing marker should be
  2. Re-run the exact recovery command printed after 'Action:' (or a plain `rtk init` for that agent) — it re-adds a complete balanced block
  3. Verify your own content around the block is intact before re-running

Example fix

# CLAUDE.md before (malformed: start marker with no closing marker)
<!-- rtk-instructions
...leftover instructions...
<EOF>

# after cleanup + re-run
delete from '<!-- rtk-instructions' to the intended block end, then:
rtk init -g   # re-adds a complete, balanced block
Defensive patterns

Strategy: validation

Validate before calling

# bash: verify RTK block markers are balanced before init
F=CLAUDE.md
S=$(grep -cF '<!-- rtk-instructions' "$F" 2>/dev/null || echo 0)
E=$(grep -cF '<!-- /rtk-instructions -->' "$F" 2>/dev/null || echo 0)
[ "$S" -eq "$E" ] || { echo "unbalanced RTK markers in $F ($S start / $E end)" >&2; exit 2; }

Try / catch

Treat this specific bail as a stop-and-fix signal in automation: capture the file path and 'Location: line N' from stderr, fail the init step, and require a human edit before retry — retrying unchanged always fails.

Prevention

When it happens

Trigger: A previous init was interrupted mid-write, a git merge/revert kept the opening marker but dropped the closing one, or a teammate deleted part of the block; any subsequent `rtk init` for that agent bails at src/hooks/init.rs:2573.

Common situations: Merge conflicts in CLAUDE.md/AGENTS.md resolved by hand; partial reverts of an init commit; instruction files truncated by an editor or LLM run.

Understand the failure class

Related errors


AI-assisted analysis of rtk-ai/rtk@d977e1c316 (2026-08-16). Data as JSON: /api/errors/4a238171353dd9bc. Report an issue: GitHub.