{"record":{"id":"372f8dc71bb584fc","repo":"gitbutlerapp/gitbutler","slug":"found-only-the-gitbutler-managed-block-start-marker-refusing","errorCode":null,"errorMessage":"Found only the GitButler managed block start marker. Refusing to edit a partial managed block.","messagePattern":"Found only the GitButler managed block start marker\\. Refusing to edit a partial managed block\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but/src/command/agent/files.rs","lineNumber":103,"sourceCode":"\n/// Rewrite `block` to use CRLF line endings when `existing` already does, so a\n/// replaced or appended block does not introduce mixed line endings.\nfn match_line_endings(existing: &str, block: &str) -> String {\n    if existing.contains(\"\\r\\n\") {\n        block.replace(\"\\r\\n\", \"\\n\").replace('\\n', \"\\r\\n\")\n    } else {\n        block.to_string()\n    }\n}\n\npub(super) fn upsert_managed_block(existing: &str, block: &str) -> Result<String> {\n    let start = find_line_anchored(existing, MANAGED_BLOCK_START, 0);\n    let end = find_line_anchored(existing, MANAGED_BLOCK_END, 0);\n\n    match (start, end) {\n        // No managed block yet: append a fresh one.\n        (None, None) => return Ok(append_managed_block(existing, block)),\n        (Some(_), None) => anyhow::bail!(\n            \"Found only the GitButler managed block start marker. Refusing to edit a partial managed block.\"\n        ),\n        (None, Some(_)) => anyhow::bail!(\n            \"Found only the GitButler managed block end marker. Refusing to edit a partial managed block.\"\n        ),\n        (Some(start), Some(end)) if end < start => anyhow::bail!(\n            \"Found GitButler managed block markers in the wrong order (end before start). Refusing to edit a malformed managed block.\"\n        ),\n        // Well-formed: a start marker with an end after it. Fall through to replace.\n        (Some(_), Some(_)) => {}\n    }\n\n    // Replace the first block with the fresh one and drop any extra blocks\n    // (e.g. left over from an earlier buggy run), so the file converges to\n    // exactly one block.\n    let mut spans = Vec::new();\n    for span in managed_block_spans(existing)? {\n        let mut block_end = span.end;","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but/src/command/agent/files.rs#L85-L121","documentation":"GitButler's agent-managed file block (e.g. an instructions file section) is delimited by a start and end marker. This error is thrown when only the start marker exists, so the managed block is incomplete. The tool refuses to edit a partial block rather than corrupting the file.","triggerScenarios":"Calling upsert_managed_block (via `but agent` file upserts) on a file where find_line_anchored finds MANAGED_BLOCK_START but no MANAGED_BLOCK_END — typically after a user manually deleted the end marker or a truncated write/merge removed it.","commonSituations":"Users hand-editing their AGENT.md/instructions file and deleting the closing marker; merge conflicts or partial checkouts dropping the block tail; copy-pasting only the header marker into a new file.","solutions":["Open the file and restore the missing GitButler managed block end marker after the start marker.","Alternatively delete the start marker entirely so upsert_managed_block appends a fresh, complete block.","Re-run the upsert command after the file contains either a complete block or no markers."],"exampleFix":"// before (broken file)\n<!-- GITBUTLER-MANAGED-BLOCK:START -->\n// after (fixed file)\n<!-- GITBUTLER-MANAGED-BLOCK:START -->\n...content...\n<!-- GITBUTLER-MANAGED-BLOCK:END -->","handlingStrategy":"validation","validationCode":"const content = fs.readFileSync(file, 'utf8');\nconst starts = content.split('\\n').filter(l => l.includes('GITBUTLER-MANAGED-BLOCK:START')).length;\nconst ends = content.split('\\n').filter(l => l.includes('GITBUTLER-MANAGED-BLOCK:END')).length;\nif (starts !== ends || starts === 0) throw new Error(`Unbalanced managed-block markers in ${file}: ${starts} start, ${ends} end`);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never hand-edit the lines between managed block markers; only edit outside the block.","After merging or conflict resolution, diff the file and verify both markers survive in order.","Teach linters/formatters to ignore the managed block region."],"tags":["gitbutler","managed-block","file-editing","cli"],"backgroundTag":"invalid-state-transition","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}