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
- 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
- Re-run the exact recovery command printed after 'Action:' (or a plain `rtk init` for that agent) — it re-adds a complete balanced block
- 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
- Commit instruction files (CLAUDE.md/AGENTS.md) immediately after rtk init so a broken block is one git checkout away
- Resolve merge conflicts on instruction files by dropping the whole RTK block, never half of it
- Run `rtk init --dry-run` after merges touching these files; Malformed is detected before any write
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
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- --codex cannot be combined with --opencode
- --codex cannot be combined with --claude-md
- --codex cannot be combined with --hook-only
- --codex cannot be combined with --auto-patch
- --codex cannot be combined with --no-patch
AI-assisted analysis of rtk-ai/rtk@d977e1c316 (2026-08-16).
Data as JSON: /api/errors/4a238171353dd9bc.
Report an issue: GitHub.