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

  1. Re-type the value by hand instead of copy-pasting from a rich-text source.
  2. 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.
  3. 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

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


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/8eab48b20b7e92a1. Report an issue: GitHub.