gitbutlerapp/gitbutler · error
Found only the GitButler managed block end marker. Refusing…
Error message
Found only the GitButler managed block end marker. Refusing to edit a partial managed block.
What it means
The mirror case of the partial-start-marker error: only the end marker of the GitButler managed block was found. Since a well-formed block requires start-then-end, the tool refuses to upsert to avoid corrupting surrounding user content.
Solutions
- Re-add the GitButler managed block start marker above the end marker.
- Or remove the orphaned end marker so a complete fresh block can be appended.
- Re-run the upsert once the markers are balanced.
Example fix
// before ...content... <!-- GITBUTLER-MANAGED-BLOCK:END --> // after <!-- GITBUTLER-MANAGED-BLOCK:START --> ...content... <!-- GITBUTLER-MANAGED-BLOCK:END -->
Defensive patterns
Strategy: validation
Validate before calling
const content = fs.readFileSync(file, 'utf8');
const startIdx = content.indexOf('GITBUTLER-MANAGED-BLOCK:START');
const endIdx = content.indexOf('GITBUTLER-MANAGED-BLOCK:END');
if (endIdx !== -1 && startIdx === -1) throw new Error(`Orphaned end marker in ${file}; re-add the start marker`); Prevention
- Delete the entire managed block (both markers) rather than individual lines.
- Verify marker balance after any automated rewrite of the file.
- Keep managed-block edits flowing through `but agent` commands only.
When it happens
Trigger: upsert_managed_block finds MANAGED_BLOCK_END with no preceding MANAGED_BLOCK_START — e.g. the user deleted the start marker line, or an automated edit truncated the block header.
Common situations: Manual cleanup of instruction files that removed the header comment; linters/formatters stripping the start marker line; merge conflict resolution keeping only the tail.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Found only the GitButler managed block start marker…
- Found GitButler managed block markers in the wrong order…
- Ambiguous branch ' ', matches multiple items
- Ambiguous branch ' ', matches multiple items
- `but land` requires an active GitButler workspace…
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/15c2bbcb139beb11.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but/src/command/agent/files.rs:106
fn match_line_endings(existing: &str, block: &str) -> String {
if existing.contains("\r\n") {
block.replace("\r\n", "\n").replace('\n', "\r\n")
} else {
block.to_string()
}
}
pub(super) fn upsert_managed_block(existing: &str, block: &str) -> Result<String> {
let start = find_line_anchored(existing, MANAGED_BLOCK_START, 0);
let end = find_line_anchored(existing, MANAGED_BLOCK_END, 0);
match (start, end) {
// No managed block yet: append a fresh one.
(None, None) => return Ok(append_managed_block(existing, block)),
(Some(_), None) => anyhow::bail!(
"Found only the GitButler managed block start marker. Refusing to edit a partial managed block."
),
(None, Some(_)) => anyhow::bail!(
"Found only the GitButler managed block end marker. Refusing to edit a partial managed block."
),
(Some(start), Some(end)) if end < start => anyhow::bail!(
"Found GitButler managed block markers in the wrong order (end before start). Refusing to edit a malformed managed block."
),
// Well-formed: a start marker with an end after it. Fall through to replace.
(Some(_), Some(_)) => {}
}
// Replace the first block with the fresh one and drop any extra blocks
// (e.g. left over from an earlier buggy run), so the file converges to
// exactly one block.
let mut spans = Vec::new();
for span in managed_block_spans(existing)? {
let mut block_end = span.end;
if existing[block_end..].starts_with("\r\n") {
block_end += 2;
} else if existing[block_end..].starts_with('\n') {View on GitHub (pinned to 58e5313667)