When branch_name_template uses {{label}}, the raw GitHub label name is substituted into the branch name without any sanitization. Labels are free-form and frequently scoped with a colon or slash, so a template like {{prefix}}{{label}}/{{description}} on an issue whose first label is area:permissions produces a branch name containing :.
That name then reaches validateBranchName in src/github/operations/branch.ts, which rejects : (along with the other special git characters). The error is caught by the surrounding try/catch in the branch setup block, which calls process.exit(1) — so instead of a bad-branch-name warning, the whole action run dies.
This is easy to hit because scoped labels are common — this repo itself uses labels like area:permissions and provider:1p. Any consumer that opts into a {{label}}-based template and runs on an issue carrying such a label will crash.
The inconsistency is with {{description}}, which is already sanitized: generateBranchName runs the title through extractDescription, which kebab-cases it and strips everything outside [a-z0-9-]. {{label}} is the only free-text template variable that skips that step — it's substituted verbatim. action.yml even documents {{description}} as being kebab-cased but says nothing about {{label}}, so the raw substitution isn't the intended contract.
Repro: set branch_name_template: "{{prefix}}{{label}}/{{entityNumber}}" and trigger the action on an issue whose first label is area:permissions. The generated branch name is claude/area:permissions/123, validateBranchName throws, and the run exits with code 1.
Fix is to sanitize the label into a git-safe segment before substitution, the same way descriptions are handled. I'll open a PR that does this and adds regression tests.
(Related, out of scope for the fix I'm sending: a title made up entirely of non-alphanumerics makes {{description}} sanitize to an empty string, so a template like {{prefix}}{{description}}/{{entityNumber}} yields a // double slash, which validateBranchName also rejects. Same failure mode, different variable — worth a follow-up.)
When
branch_name_templateuses{{label}}, the raw GitHub label name is substituted into the branch name without any sanitization. Labels are free-form and frequently scoped with a colon or slash, so a template like{{prefix}}{{label}}/{{description}}on an issue whose first label isarea:permissionsproduces a branch name containing:.That name then reaches
validateBranchNameinsrc/github/operations/branch.ts, which rejects:(along with the other special git characters). The error is caught by the surroundingtry/catchin the branch setup block, which callsprocess.exit(1)— so instead of a bad-branch-name warning, the whole action run dies.This is easy to hit because scoped labels are common — this repo itself uses labels like
area:permissionsandprovider:1p. Any consumer that opts into a{{label}}-based template and runs on an issue carrying such a label will crash.The inconsistency is with
{{description}}, which is already sanitized:generateBranchNameruns the title throughextractDescription, which kebab-cases it and strips everything outside[a-z0-9-].{{label}}is the only free-text template variable that skips that step — it's substituted verbatim.action.ymleven documents{{description}}as being kebab-cased but says nothing about{{label}}, so the raw substitution isn't the intended contract.Repro: set
branch_name_template: "{{prefix}}{{label}}/{{entityNumber}}"and trigger the action on an issue whose first label isarea:permissions. The generated branch name isclaude/area:permissions/123,validateBranchNamethrows, and the run exits with code 1.Fix is to sanitize the label into a git-safe segment before substitution, the same way descriptions are handled. I'll open a PR that does this and adds regression tests.
(Related, out of scope for the fix I'm sending: a title made up entirely of non-alphanumerics makes
{{description}}sanitize to an empty string, so a template like{{prefix}}{{description}}/{{entityNumber}}yields a//double slash, whichvalidateBranchNamealso rejects. Same failure mode, different variable — worth a follow-up.)