abhigyanpatwari/GitNexus · error · GitNexusRcError
${source}: value contains control or hidden/bidirectional ch
Error message
${source}: value contains control or hidden/bidirectional characters, which are not allowed. What it means
Thrown by assertNoHiddenChars() (reachable from validateBranchName, the 'string' config kind, and the 'string-array' kind) when a config value contains a control character (< 0x20), DEL (0x7f), zero-width characters, bidirectional overrides, or a BOM. These characters are invisible to reviewers but can alter how generated AGENTS.md/CLAUDE.md content is interpreted by an agent, so they are rejected at the single chokepoint before any file is written.
Source
Thrown at gitnexus/src/cli/analyze-config.ts:146
* Reject control characters and hidden / bidirectional Unicode in a string
* value. These have no legitimate place in a branch name, registry name, or
* device string, and would otherwise let a committed config smuggle invisible
* controls into generated AGENTS.md / CLAUDE.md content.
*/
const isHiddenOrControl = (codePoint: number): boolean =>
codePoint < 0x20 ||
codePoint === 0x7f ||
(codePoint >= 0x200b && codePoint <= 0x200f) || // zero-width + LRM/RLM
(codePoint >= 0x202a && codePoint <= 0x202e) || // bidi embeddings/overrides
(codePoint >= 0x2060 && codePoint <= 0x2064) || // word-joiner + invisible math
(codePoint >= 0x2066 && codePoint <= 0x206f) || // bidi isolates + deprecated
codePoint === 0xfeff; // BOM / zero-width no-break space
const assertNoHiddenChars = (value: string, source: string): void => {
for (const ch of value) {
const cp = ch.codePointAt(0);
if (cp !== undefined && isHiddenOrControl(cp)) {
throw new GitNexusRcError(
`${source}: value contains control or hidden/bidirectional characters, which are not allowed.`,
);
}
}
};
/**
* Validate a user-supplied branch name (from CLI or `.gitnexusrc`). Returns the
* trimmed name or throws {@link GitNexusRcError}. 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 GitNexusRcError(`${source}: branch name must not be empty.`);
}
if (trimmed.length > BRANCH_MAX_LENGTH) {
throw new GitNexusRcError(`${source}: branch name is too long (max ${BRANCH_MAX_LENGTH}).`);View on GitHub (pinned to d540b00184)
Solutions
- Re-type the value by hand instead of copy-pasting from a rich-text source.
- Strip invisible characters before committing: run the value through a sanitizer that removes U+200B-200F, U+202A-202E, U+2060-206F, and U+FEFF.
- Inspect the file with a hex viewer or `cat -A` to locate the offending byte, then remove it.
Example fix
// before (.gitnexusrc, branch name has a trailing zero-width space)
{ "defaultBranch": "main\u200b" }
// after
{ "defaultBranch": "main" } Defensive patterns
Strategy: validation
Validate before calling
function stripHiddenChars(value: string): string {
return Array.from(value)
.filter((ch) => {
const cp = ch.codePointAt(0)!;
return !(cp < 0x20 || cp === 0x7f ||
(cp >= 0x200b && cp <= 0x200f) ||
(cp >= 0x202a && cp <= 0x202e) ||
(cp >= 0x2060 && cp <= 0x2064) ||
(cp >= 0x2066 && cp <= 0x206f) ||
cp === 0xfeff);
})
.join('');
} Type guard
function isFreeOfHiddenChars(value: string): boolean {
for (const ch of value) {
const cp = ch.codePointAt(0)!;
if (cp < 0x20 || cp === 0x7f ||
(cp >= 0x200b && cp <= 0x200f) ||
(cp >= 0x202a && cp <= 0x202e) ||
(cp >= 0x2060 && cp <= 0x2064) ||
(cp >= 0x2066 && cp <= 0x206f) ||
cp === 0xfeff) return false;
}
return true;
} Prevention
- Avoid copy-pasting branch/repo names from chat clients or web pages that insert zero-width chars.
- Sanitize editor BOM settings: save .gitnexusrc as UTF-8 without BOM.
- Run `grep -P '[\x{200b}-\x{200f}\x{202a}-\x{202e}]' .gitnexusrc` before committing to catch invisible chars.
When it happens
Trigger: A .gitnexusrc value containing a pasted zero-width space (U+200B), a bidi override (U+202E), a stray tab/newline inside a string, or a BOM (U+FEFF) carried over from a Windows editor copy-paste.
Common situations: Copying a branch or repo name from a web page or chat client that inserted a zero-width joiner; committing a config file edited in an editor that saved a BOM inside a string value; a malicious or accidental homoglyph attack on agent instructions.
Related errors
- ${source}: branch name must not contain a backtick (it would
- ${source} must not contain Markdown-significant characters (
- Invalid backend URL: must be a well-formed http:// or https:
- Backend URL must use http:// or https:// (got ${parsed.proto
- ${source}: branch name contains characters not allowed in a
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/8eab48b20b7e92a1.
Report an issue: GitHub.