{"record":{"id":"44b9049776cf322a","repo":"gitbutlerapp/gitbutler","slug":"hashtag-cannot-be-empty","errorCode":null,"errorMessage":"Hashtag cannot be empty","messagePattern":"Hashtag cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but/src/command/legacy/push.rs","lineNumber":1075,"sourceCode":"\n    if !gerrit_mode {\n        return Ok(vec![]);\n    }\n\n    let mut flags = Vec::new();\n\n    // Handle Wip/Ready - Ready is default if neither is specified\n    if args.wip {\n        flags.push(but_gerrit::PushFlag::Wip);\n    } else {\n        // Default to Ready, or explicit Ready\n        flags.push(but_gerrit::PushFlag::Ready);\n    }\n\n    // Handle hashtags - can be multiple\n    for hashtag in &args.hashtag {\n        if hashtag.trim().is_empty() {\n            return Err(anyhow::anyhow!(\"Hashtag cannot be empty\"));\n        }\n        flags.push(but_gerrit::PushFlag::Hashtag(hashtag.clone()));\n    }\n\n    // Handle topic - at most one\n    if let Some(topic) = &args.topic {\n        if topic.trim().is_empty() {\n            return Err(anyhow::anyhow!(\"Topic cannot be empty\"));\n        }\n        flags.push(but_gerrit::PushFlag::Topic(topic.clone()));\n    } else if args.topic_from_branch {\n        flags.push(but_gerrit::PushFlag::Topic(branch_name.to_string()));\n    }\n\n    // Handle private flag\n    if args.private {\n        flags.push(but_gerrit::PushFlag::Private);\n    }","sourceCodeStart":1057,"sourceCodeEnd":1093,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but/src/command/legacy/push.rs#L1057-L1093","documentation":"With gerrit mode enabled, each `--hashtag` value is trimmed and must be non-empty before it becomes `but_gerrit::PushFlag::Hashtag`. Empty or whitespace-only input is rejected because a Gerrit hashtag is review metadata and cannot be blank.","triggerScenarios":"Running `but push --hashtag \"\"` or `--hashtag \"   \"` in a Gerrit-enabled repo; a shell loop expanding an empty variable into the flag.","commonSituations":"CI variable left empty and passed through a loop; copy-paste leaving a placeholder value; accidental empty element in a flag list.","solutions":["Remove the empty --hashtag argument","Give the hashtag a real value: `but push --hashtag my-team`","Guard scripts to skip empty values when building the flag list"],"exampleFix":"# before\nbut push --hashtag \"\"\n# error: Hashtag cannot be empty\n\n# after\nbut push --hashtag my-team","handlingStrategy":"validation","validationCode":"# Drop empty/blank hashtags before invoking but\nargs=()\nfor tag in \"${hashtags[@]}\"; do\n  [ -n \"${tag//[[:space:]]/}\" ] && args+=(--hashtag \"$tag\")\ndone\nbut push \"${args[@]}\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate list-valued flags in wrappers before exec","Quote CI variables so empty ones are visible instead of silently forwarded","Fail fast on blank inputs rather than passing them through"],"tags":["gerrit","push","hashtag","argument-validation"],"backgroundTag":"empty-string-argument","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}