abhigyanpatwari/GitNexus · error · InvalidBranchError
: branch name must not end with "." or have a path…
Error message
${source}: branch name must not end with "." or have a path component starting with ".". What it means
validateBranchName rejects names ending with '.' or containing a '/'-separated component that starts with '.', matching git check-ref-format (git refuses refs like 'feature.' or '.hidden/foo'). The library throws early so hidden-file-style or trailing-dot names fail validation instead of inside the git subprocess.
Solutions
- Remove the trailing dot and any leading dots from path components: `name.split("/").map(p => p.replace(/^\.+/, "")).join("/").replace(/\.+$/, "")`.
- Fix the generator deriving branch names from file paths so dotfiles are skipped or renamed.
- Retype the branch name — trailing periods usually come from copy-pasting prose.
Example fix
// before
const branch = filePath; // ".github/workflows"
validateBranchName(branch);
// after
const branch = filePath.split("/").map(p => p.replace(/^\./, "")).join("/"); // "github/workflows"
validateBranchName(branch); Defensive patterns
Strategy: validation
Validate before calling
function hasDotIssues(name) {
return typeof name === "string" &&
(name.endsWith(".") || name.split("/").some(p => p.startsWith(".")));
}
branch = branch.split("/").map(p => p.replace(/^\.+/, "")).join("/").replace(/\.+$/, ""); Type guard
function isDotSafeBranch(v: unknown): v is string {
return typeof v === "string" && !v.endsWith(".") &&
!v.split("/").some(p => p.startsWith("."));
} Try / catch
try {
validateBranchName(branch, "generator");
} catch (e) {
if (e instanceof InvalidBranchError && e.message.includes('"."')) {
branch = branch.split("/").map(p => p.replace(/^\./, "")).join("/").replace(/\.$/, "");
validateBranchName(branch, "generator");
} else throw e;
} Prevention
- Do not derive branch names directly from filesystem paths; skip or rename dotfile segments.
- Trim trailing punctuation when a branch name comes from copy-pasted text or prose.
- Reject trailing '.' in any user-supplied ref input at your boundary.
- Run generated names through git check-ref-format --branch in tests.
When it happens
Trigger: Calling validateBranchName with 'release.', 'v1.', '.hidden', '.github/workflows', or names built from filesystem paths whose segments start with a dot, e.g. concatenating a directory path into a branch name.
Common situations: Branch names derived from file paths (config generators that turn '.env/foo' into a branch); accidental trailing '.' from sentence-ending copy-paste ('branch named feature.'); template strings appending periods.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- err.message (InvalidBranchError rethrown as GitNexusRcError…
- : branch name contains characters not allowed in a git ref…
- : branch name is too long (max ).
- : branch name must not be empty.
- : branch name must not be "HEAD".
AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-09-15).
Data as JSON: /api/errors/cc872cc375b4a310.
Report an issue: GitHub.
Appendix: source
Thrown at gitnexus/src/core/git-ref.ts:112
// git subprocess instead of here. No real branch can violate them — git
// could not have created one — so nothing that works today starts failing.
if (trimmed.endsWith('.lock') || trimmed.split('/').some((part) => part.endsWith('.lock'))) {
throw new InvalidBranchError(`${source}: branch name must not end with ".lock".`);
}
if (trimmed.startsWith('/') || trimmed.endsWith('/')) {
throw new InvalidBranchError(`${source}: branch name must not start or end with "/".`);
}
if (trimmed.includes('//')) {
throw new InvalidBranchError(`${source}: branch name must not contain consecutive slashes.`);
}
if (trimmed === '@') {
throw new InvalidBranchError(`${source}: branch name must not be the single character "@".`);
}
if (trimmed.includes('@{')) {
throw new InvalidBranchError(`${source}: branch name must not contain "@{".`);
}
if (trimmed.endsWith('.') || trimmed.split('/').some((part) => part.startsWith('.'))) {
throw new InvalidBranchError(
`${source}: branch name must not end with "." or have a path component starting with ".".`,
);
}
// Git permits a backtick in a ref, but the branch is embedded inside a
// Markdown inline-code span in the generated AGENTS.md/CLAUDE.md regression
// example, where a backtick would close the span early and let the rest of
// the template render as instruction text. Reject it at this single
// chokepoint so all three tiers (CLI flag, .gitnexusrc, auto-detect via
// sanitizeDetectedBranch) are covered (#1996 tri-review P1).
if (trimmed.includes('`')) {
throw new InvalidBranchError(
`${source}: branch name must not contain a backtick (it would break the generated Markdown).`,
);
}
return trimmed;
}
View on GitHub (pinned to ac9a4e9abd)