{"record":{"id":"a0a6821eecf90166","repo":"stablyai/orca","slug":"invalid-branch-name","errorCode":null,"errorMessage":"Invalid branch name","messagePattern":"Invalid branch name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/main/git/worktree.ts","lineNumber":1385,"sourceCode":"    return false\n  }\n  await forceDeleteLocalBranch(repoPath, branchName, branchHead, (args, cwd) =>\n    gitExecFileAsync(args, gitExecOptions(cwd, options))\n  )\n  return true\n}\n\nexport async function forceDeleteLocalBranch(\n  repoPath: string,\n  branchName: string,\n  expectedHead: string,\n  runGit: (args: string[], cwd: string) => Promise<{ stdout: string; stderr: string }> = (\n    args,\n    cwd\n  ) => gitExecFileAsync(args, { cwd })\n): Promise<void> {\n  if (!branchName || branchName.includes('\\0')) {\n    throw new Error('Invalid branch name')\n  }\n  if (!expectedHead) {\n    throw new Error(\n      `Cannot force-delete local branch \"${branchName}\" without the commit Git preserved.`\n    )\n  }\n  if (await isLocalBranchCheckedOut(repoPath, branchName, runGit)) {\n    throw new Error(`Local branch \"${branchName}\" is checked out in another worktree.`)\n  }\n  // Why: stale toast actions must not delete a branch that moved; `update-ref -d` deletes only if the ref still == expectedHead.\n  try {\n    await runGit(['update-ref', '-d', `refs/heads/${branchName}`, expectedHead], repoPath)\n  } catch {\n    throw new Error(\n      `Local branch \"${branchName}\" changed after the workspace was deleted. Review it before deleting it.`\n    )\n  }\n  if (await isLocalBranchCheckedOut(repoPath, branchName, runGit)) {","sourceCodeStart":1367,"sourceCodeEnd":1403,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/git/worktree.ts#L1367-L1403","documentation":"Thrown at the top of forceDeleteLocalBranch when branchName is falsy (empty string, undefined, null) OR contains a NUL byte (`\\0`). The NUL check is an argv-injection guard: git uses NUL as a record separator in porcelain output and a NUL in a branch name could smuggle additional ref arguments into `update-ref`. This is a programmer-error guard, not a recoverable runtime condition.","triggerScenarios":"A stale toast action firing after the branch name was cleared from UI state; a serialized action whose branch field was never populated; a malicious or malformed ref name reaching the function via a crafted remote; testing code that passes undefined by mistake.","commonSituations":"UI 'delete branch' toast surviving a workspace reload that nulled the branch field; a race where the worktree is removed before the branch-delete action captures its name; fuzzed/malicious input attempting argument injection.","solutions":["Inspect the call site: ensure branchName is always a non-empty string before invoking forceDeleteLocalBranch.","If the value is coming from a serialized toast action, validate and discard the action when branchName is empty rather than calling through.","Sanitize ref names at the trust boundary — reject any containing NUL, whitespace, or `..`/`~`/`^`/`:` per git-check-ref-format before they reach this function."],"exampleFix":"// before\nawait forceDeleteLocalBranch(repoPath, maybeBranch, head)\n\n// after\nif (!maybeBranch || maybeBranch.includes('\\0')) {\n  discardStaleToast()\n  return\n}\nawait forceDeleteLocalBranch(repoPath, maybeBranch, head)","handlingStrategy":"validation","validationCode":"function isValidBranchNameForDelete(name: unknown): name is string {\n  return typeof name === 'string' && name.length > 0 && !name.includes('\\0')\n}","typeGuard":"function isValidBranchNameForDelete(name: unknown): name is string {\n  return typeof name === 'string' && name.length > 0 && !name.includes('\\0')\n}","tryCatchPattern":null,"preventionTips":["Validate branch names at the UI/API trust boundary, not just at the git call.","Discard stale toast actions whose payload is missing a branch name.","Reject ref names failing git-check-ref-format before they reach deletion."],"tags":["git","branch","validation","argv-injection","programmer-error"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}