{"record":{"id":"73f7cb0e63881451","repo":"abhigyanpatwari/GitNexus","slug":"source-branch-name-must-not-contain-73f7cb","errorCode":null,"errorMessage":"${source}: branch name must not contain \"@{\".","messagePattern":"(.+?): branch name must not contain \"@\\{\"\\.","errorType":"validation","errorClass":"InvalidBranchError","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/git-ref.ts","lineNumber":109,"sourceCode":"  // The remaining `git check-ref-format` rules. Without these the validator\n  // accepted refs git itself refuses (`feature.lock`, `/feature`, `feature/`,\n  // `feature//next`, `@`, `.hidden`), so the failure surfaced later from the\n  // git subprocess instead of here. No real branch can violate them — git\n  // could not have created one — so nothing that works today starts failing.\n  if (trimmed.endsWith('.lock') || trimmed.split('/').some((part) => part.endsWith('.lock'))) {\n    throw new InvalidBranchError(`${source}: branch name must not end with \".lock\".`);\n  }\n  if (trimmed.startsWith('/') || trimmed.endsWith('/')) {\n    throw new InvalidBranchError(`${source}: branch name must not start or end with \"/\".`);\n  }\n  if (trimmed.includes('//')) {\n    throw new InvalidBranchError(`${source}: branch name must not contain consecutive slashes.`);\n  }\n  if (trimmed === '@') {\n    throw new InvalidBranchError(`${source}: branch name must not be the single character \"@\".`);\n  }\n  if (trimmed.includes('@{')) {\n    throw new InvalidBranchError(`${source}: branch name must not contain \"@{\".`);\n  }\n  if (trimmed.endsWith('.') || trimmed.split('/').some((part) => part.startsWith('.'))) {\n    throw new InvalidBranchError(\n      `${source}: branch name must not end with \".\" or have a path component starting with \".\".`,\n    );\n  }\n  // Git permits a backtick in a ref, but the branch is embedded inside a\n  // Markdown inline-code span in the generated AGENTS.md/CLAUDE.md regression\n  // example, where a backtick would close the span early and let the rest of\n  // the template render as instruction text. Reject it at this single\n  // chokepoint so all three tiers (CLI flag, .gitnexusrc, auto-detect via\n  // sanitizeDetectedBranch) are covered (#1996 tri-review P1).\n  if (trimmed.includes('`')) {\n    throw new InvalidBranchError(\n      `${source}: branch name must not contain a backtick (it would break the generated Markdown).`,\n    );\n  }\n  return trimmed;","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/ac9a4e9abd8fd3058c070b72c23402a4f887929a/gitnexus/src/core/git-ref.ts#L91-L127","documentation":"validateBranchName rejects names containing '@{', which in git ref syntax is the reflog/revision prefix (e.g. '@{1}', 'branch@{yesterday}') and can never be part of a real branch name. Throwing here keeps reflog expressions out of a branch-name parameter, per git check-ref-format rules.","triggerScenarios":"Calling validateBranchName with values like 'HEAD@{1}', 'main@{u}', or a revision expression pasted into the branch argument, e.g. `--branch main@{yesterday}`.","commonSituations":"Users copying reflog queries or upstream shorthand ('@{u}', '@{push}') into a branch field; scripts interpolating `git rev-parse` expressions; docs examples mixing revision syntax with branch parameters.","solutions":["Pass a plain branch name; resolve the reflog/upstream expression first, e.g. `git rev-parse --abbrev-ref main@{u}`.","Use the library's revision/commit options for '@{...}' expressions instead of the branch parameter.","Strip or reject '@{' at your input boundary before invoking the API."],"exampleFix":"// before\nvalidateBranchName(\"main@{u}\");\n// after\nconst branch = execSync(\"git rev-parse --abbrev-ref main@{u}\").toString().trim(); // e.g. \"origin/main\"\nvalidateBranchName(branch);","handlingStrategy":"validation","validationCode":"function hasReflogExpr(name) { return typeof name === \"string\" && name.includes(\"@{\"); }\nif (hasReflogExpr(branch)) throw new Error(`'${branch}' is a revision expression, not a branch`);","typeGuard":"function isPlainRef(v: unknown): v is string {\n  return typeof v === \"string\" && !v.includes(\"@{\");\n}","tryCatchPattern":"try {\n  validateBranchName(branch, \"cli\");\n} catch (e) {\n  if (e instanceof InvalidBranchError && e.message.includes('\"@{\"')) {\n    console.error(\"Resolve @{...} expressions with git rev-parse first.\");\n    process.exitCode = 2;\n  } else throw e;\n}","preventionTips":["Resolve reflog/upstream syntax ('main@{u}', 'HEAD@{1}') to a concrete ref before passing it.","Keep revision expressions in revision parameters only.","Add '@{' to your input-sanitization deny-list for branch fields.","Educate users that branch parameters accept plain names only."],"tags":["git","branch-name","validation"],"backgroundTag":"invalid-identifier-format","analyzedSha":"ac9a4e9abd8fd3058c070b72c23402a4f887929a","analyzedAt":"2026-09-15T23:29:44.066Z","contentChangedAt":"2026-09-15T23:29:44.066Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}