abhigyanpatwari/GitNexus · warning · GitNexusRcError
: value contains control or hidden/bidirectional…
Error message
${source}: value contains control or hidden/bidirectional characters, which are not allowed. What it means
On DB open, GitNexus found WAL files that LadybugDB had quarantined (renamed to `${dbPath}.wal.missing-shadow.<ts>-<rand>` by quarantineWalForMissingShadow) after an unrecoverable prior crash, and deleted them. Quarantined WALs are permanently detached from the live store and never reopened, so removal is safe regardless of whether the main DB exists. A reclaim failure (e.g. transient EBUSY from antivirus) never blocks DB startup.
Solutions
- Treat a single occurrence after a crash as expected recovery — no action required
- If it repeats, capture why runs crash in the first place (OOM, SIGKILL, disk full) and fix that root cause
- Add the GitNexus storage directory to antivirus exclusions so sidecars are not locked/removed mid-run
- Run `gitnexus clean` and re-index if you suspect accumulated crash debris in the storage dir
Defensive patterns
Strategy: fallback
Validate before calling
import fs from 'node:fs/promises';
import path from 'node:path';
// before opening the DB: detect leftover quarantines from a prior crash
const dir = path.dirname(dbPath);
const quarantined = (await fs.readdir(dir).catch(() => []))
.filter((f) => f.includes('.wal.missing-shadow.'));
if (quarantined.length > 0) {
// expect reclaim warns on open; investigate what crashed the previous run
} Prevention
- Fix the root cause of crashes (OOM, forced kills) rather than relying on reclaim
- Exclude the storage directory from antivirus so sidecars are not locked mid-run
- Run `gitnexus clean` before a fresh full re-index to clear accumulated crash debris
When it happens
Trigger: cleanQuarantinedMissingShadowWals(dbPath) returns files matching the quarantine rename pattern — i.e. a previous run crashed in a way where the WAL's shadow sidecar was missing and LadybugDB could not recover, so it set the WAL aside instead of deleting it.
Common situations: Power loss or forced kill during heavy write load (the #1618-style crash loop); antivirus quarantining or locking a .shadow sidecar mid-checkpoint so the next open finds the WAL unrecoverable; repeated occurrences point at systematic crash-then-recover cycles on the same machine.
Related errors
- GitNexus: failed to reclaim missing-shadow WAL quarantines
- Cannot park after an in-place FTS abort )` : ''}. The…
- Cannot park after an in-place FTS abort )` : ''}. The…
- FTS_READER_UNREPAIRABLE
- GitNexus could not move the LadybugDB WAL sidecar at
AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-08-20).
Data as JSON: /api/errors/8eab48b20b7e92a1.
Report an issue: GitHub.
Appendix: source
Thrown at gitnexus/src/cli/analyze-config.ts:152
* 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}. Rules live in
* `core/git-ref.ts`; this wrapper keeps the CLI / `.gitnexusrc` error type.
*/
export function validateBranchName(value: string, source: string): string {
try {
return validateBranchNameCore(value, source);
} catch (err) {
if (err instanceof InvalidBranchError) {
throw new GitNexusRcError(err.message);
}View on GitHub (pinned to ac9a4e9abd)