abhigyanpatwari/GitNexus · error · InvalidBranchError
: branch name contains characters not allowed in a git ref…
Error message
${source}: branch name contains characters not allowed in a git ref (~ ^ : ? * [ \). What it means
validateBranchName enforces a subset of git's ref-name rules and throws InvalidBranchError '<source>: branch name contains characters not allowed in a git ref (~ ^ : ? * [ \\).' when the name matches /[~^:?*[\\]/. Git itself forbids these characters in refs, so any such name would fail at git level anyway; the library rejects it early with a clear message.
Solutions
- Remove or replace the forbidden characters (~ ^ : ? * [ \\) with safe ones such as '-' or '/'.
- Convert path separators to '/' (or '-') when deriving names from paths: value.replace(/\\+/g, '-').
- Sanitize generated names (e.g. timestamps '2026-09-15T10:00:00Z' → '2026-09-15-100000z') before validation.
- Adopt a naming convention of lowercase alphanumerics, '-', '_', and '/' only.
Example fix
// before
const branch = `work/${new Date().toISOString()}`; // contains ':'
validateBranchName(branch, 'worktree');
// after
const branch = `work/${new Date().toISOString().replace(/[:]/g, '-')}`;
validateBranchName(branch, 'worktree'); Defensive patterns
Strategy: validation
Validate before calling
if (/[~^:?*[\\]/.test(name)) {
name = name.replace(/[~^:?*[\\]/g, '-');
} Type guard
const isGitRefSafe = (v: string): boolean => !/[~^:?*[\\]/.test(v);
Try / catch
try {
branch = validateBranchName(input, 'worktree');
} catch (e) {
if (e instanceof InvalidBranchError && /not allowed in a git ref/.test(e.message)) {
branch = validateBranchName(input.replace(/[~^:?*[\\]/g, '-'), 'worktree');
} else throw e;
} Prevention
- Restrict generated names to [A-Za-z0-9/_-] only.
- Convert path separators (especially Windows backslashes) to '-' or '/' when deriving names.
- Format timestamps for refs without colons (e.g. 2026-09-15-101500).
- Never pass glob/wildcard patterns as literal branch names.
When it happens
Trigger: Calling validateBranchName with any of ~ ^ : ? * [ or \\ in the value — e.g. 'feature:v2', 'release~1', 'fix*test', a Windows path fragment like 'feature\\foo', or glob-like names 'bug?[0-9]'.
Common situations: Deriving branch names from file paths on Windows (backslashes); using colon-separated prefixes like 'user:topic'; wildcard patterns intended for matching being passed as literal names; date strings with colons from toISOString-style formatting.
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 is too long (max ).
- : branch name must not be empty.
- : branch name must not be "HEAD".
- : branch name must not be the single character "@".
AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-09-15).
Data as JSON: /api/errors/7717b21f03aa03ae.
Report an issue: GitHub.
Appendix: source
Thrown at gitnexus/src/core/git-ref.ts:70
* Validate a user-supplied branch name. Returns the trimmed name or throws
* {@link InvalidBranchError}. Conservative but accepts the shapes real
* branches use (`feature/foo-bar`, `release/1.2`, `develop`).
*/
export function validateBranchName(value: string, source: string): string {
const trimmed = value.trim();
if (!trimmed) {
throw new InvalidBranchError(`${source}: branch name must not be empty.`);
}
if (trimmed.length > BRANCH_MAX_LENGTH) {
throw new InvalidBranchError(`${source}: branch name is too long (max ${BRANCH_MAX_LENGTH}).`);
}
assertNoHiddenChars(trimmed, source);
if (/\s/.test(trimmed)) {
throw new InvalidBranchError(`${source}: branch name must not contain whitespace.`);
}
// git ref-name rules (subset): reject characters git itself forbids in refs.
if (/[~^:?*[\\]/.test(trimmed)) {
throw new InvalidBranchError(
`${source}: branch name contains characters not allowed in a git ref (~ ^ : ? * [ \\).`,
);
}
if (trimmed.startsWith('-')) {
throw new InvalidBranchError(`${source}: branch name must not start with "-".`);
}
// Force-refspec prefix (`git fetch origin +main` / `+refs/heads/main:…`).
// Rejected here so neither the CLI nor HTTP can pass a force-update refspec
// through as a "branch" (#3199 review, defense in depth).
if (trimmed.startsWith('+')) {
throw new InvalidBranchError(`${source}: branch name must not start with "+".`);
}
// The symbolic ref HEAD (case-sensitive). A repo can have a branch named
// `head`; git itself treats only `HEAD` as the current-commit alias.
if (trimmed === 'HEAD') {
throw new InvalidBranchError(`${source}: branch name must not be "HEAD".`);
}
if (trimmed.includes('..')) {View on GitHub (pinned to ac9a4e9abd)