{"record":{"id":"489c1b9ba82aaae4","repo":"gitbutlerapp/gitbutler","slug":"line-line-number-invalid-squash-message-err","errorCode":null,"errorMessage":"line {line_number}: invalid squash message: {err}","messagePattern":"line (.+?): invalid squash message: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but-workspace/src/branch/integrate_branch_upstream/parsing.rs","lineNumber":97,"sourceCode":"                    bail!(\"line {line_number}: squash requires at least two commits\");\n                }\n                let commits = arguments\n                    .iter()\n                    .map(|commit| {\n                        resolve_commit(commit, &allowed_commits).map_err(|err| {\n                            anyhow::anyhow!(\n                                \"line {line_number}: invalid squash commit '{commit}': {err}\"\n                            )\n                        })\n                    })\n                    .collect::<Result<Vec<_>>>()?;\n                InteractiveIntegrationStep::Squash {\n                    commits,\n                    message: message_part\n                        .map(parse_message_clause)\n                        .transpose()\n                        .map_err(|err| {\n                            anyhow::anyhow!(\"line {line_number}: invalid squash message: {err}\")\n                        })?,\n                }\n            }\n            other => bail!(\"line {line_number}: unknown command '{other}'\"),\n        };\n        steps.push(step);\n    }\n\n    Ok(steps)\n}\n\nfn render_step(step: &InteractiveIntegrationStep) -> String {\n    match step {\n        InteractiveIntegrationStep::Pick { commit_id } => format!(\"pick {}\", short_id(*commit_id)),\n        InteractiveIntegrationStep::Merge { commit_id } => {\n            format!(\"merge {}\", short_id(*commit_id))\n        }\n        InteractiveIntegrationStep::Squash { commits, message } => {","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-workspace/src/branch/integrate_branch_upstream/parsing.rs#L79-L115","documentation":"Only squash accepts an optional message clause, written after a '|' separator as `| message=\"...\"` with a double-quoted string and only \\n \\r \\t \\\" \\\\ escapes. parse_message_clause (or its quoted-string parser) rejected the clause: missing 'message=' prefix, missing/incorrect opening quote, unsupported escape, trailing characters after the closing quote, or an unterminated quote/escape.","triggerScenarios":"Script lines like `squash 3333333 4444444 | msg=\"x\"` (wrong key), `... | message='x'` (single quotes), `... | message=\"a\\db\"` (bad escape), or `... | message=\"a\" trailing` (trailing text).","commonSituations":"Users writing rebase-style messages ('pick ... # message') instead of the pipe format; escaping quotes incorrectly when hand-editing.","solutions":["Use the exact form: | message=\"your text\" immediately after the commit list","Escape only \\n, \\r, \\t, \\\", \\\\ inside the quotes; put nothing after the closing quote","Omit the clause entirely to keep the default squash message"],"exampleFix":"# before\nsquash 3333333 4444444 | msg='combined fix'   # wrong key and quotes\n# after\nsquash 3333333 4444444 | message=\"combined fix\"","handlingStrategy":"validation","validationCode":"// validate the message clause shape before parsing the script\nfn message_clause_ok(clause: &str) -> bool {\n    let Some(v) = clause.strip_prefix(\"message=\") else { return false };\n    v.starts_with('\"') && v.ends_with('\"') && v.len() >= 2\n        && !v[1..v.len()-1].matches('\\\\').any(|_| { /* escapes limited to n r t \\ \" — full check in parse_quoted_string */ false })\n}","typeGuard":"fn is_valid_message_clause(clause: &str) -> bool {\n    match clause.strip_prefix(\"message=\") {\n        Some(v) => v.len() >= 2 && v.starts_with('\"') && v.ends_with('\"'),\n        None => false,\n    }\n}","tryCatchPattern":"if let Err(e) = parse_integration_steps_script(&script, &divergence) {\n    if e.to_string().contains(\"invalid squash message\") { /* show expected format: | message=\"...\" */ }\n}","preventionTips":["Use the exact clause form `| message=\"...\"` — key 'message=', double quotes, nothing trailing","Escape only \\n \\r \\t \\\" \\\\ inside the message; other backslash sequences are rejected","Omit the clause when the default squash message is acceptable"],"tags":["rust","git","rebase-plan","script-parsing","squash","integration","but-workspace"],"backgroundTag":"invalid-message-clause","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}