abhigyanpatwari/GitNexus · warning · GitNexusRcError
must be a string branch name.
Error message
${source} must be a string branch name. What it means
Rate-limited sidecar-recovery logging: warnOnce warns on the first occurrence of a condition key and again only at milestone counts (WARN_MILESTONES = [1, 10, 100, 1000, 10000]); non-milestone repeats drop to debug. This message shape — base message plus '(Nth occurrence of this condition)' — means the identical recovery condition has now recurred N times in this process. The underlying conditions are LadybugDB sidecar/WAL recovery events keyed per cause (e.g. the LADYBUGDB-CONTRACT missing-shadow error text, keyed on the locale-invariant Win32 code 2 for Windows).
Solutions
- Use the ordinal to gauge severity: 1st occurrence after a crash is expected; 10th+ means a systematic condition
- Identify the base condition in the same log line (the message before the parenthetical) and fix its cause — e.g. stop the crash loop, exclude storage dir from AV
- Run `gitnexus clean` and a fresh full analyze to reset sidecar state
- If the base message mentions shadow-sidecar errors, verify LadybugDB version compatibility (LADYBUGDB-CONTRACT comments in sidecar-recovery.ts)
Defensive patterns
Strategy: fallback
Validate before calling
import fs from 'node:fs/promises';
// before open: detect the missing-shadow precondition that feeds this recovery path
const shadowExists = await fs.access(`${dbPath}.shadow`).then(() => true, () => false);
const walExists = await fs.access(`${dbPath}.wal`).then(() => true, () => false);
if (walExists && !shadowExists) {
// a recovery event is likely on open — back up / investigate before proceeding
} Type guard
// LADYBUGDB-CONTRACT shape: native missing-shadow error, locale-invariant on Windows const isMissingShadowError = (e: unknown): e is Error => e instanceof Error && /Cannot open file.*\.shadow/.test(e.message);
Try / catch
try {
await openDb(dbPath);
} catch (e) {
if (isMissingShadowError(e)) {
// sidecar recovery will quarantine + rename the WAL; let it run, then reopen
return openDb(dbPath);
}
throw e;
} Prevention
- Use the occurrence ordinal as a recurrence meter — 10th+ means fix the systematic cause, not the symptom
- Exclude the storage directory from AV so shadow sidecars are not removed mid-checkpoint
- Re-validate LADYBUGDB-CONTRACT error matching whenever bumping the LadybugDB version
When it happens
Trigger: warnedKeyCounts.get(key) hits a milestone — the same recovery path (missing .shadow sidecar detection, quarantine, rename) fires repeatedly, e.g. every DB open finding the same missing-shadow condition, or a crash loop reopening the store.
Common situations: Persistent crash-then-reopen cycles (CI killing analyze); a storage directory where AV keeps removing/locking shadow sidecars; non-English Windows installs where error matching relies on the invariant error code rather than localized text (issue #2382). The ordinal tells you whether you have a one-off (1st) or a systematic condition (100th).
Related errors
- GitNexus: failed to remove orphan sidecar
- Cannot park after an in-place FTS abort )` : ''}. The…
- Cannot park after an in-place FTS abort )` : ''}. The…
- GitNexus could not move the LadybugDB WAL sidecar at
- GitNexus could not move the LadybugDB WAL sidecar at
AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-09-01).
Data as JSON: /api/errors/88589f6827e249e8.
Report an issue: GitHub.
Appendix: source
Thrown at gitnexus/src/cli/analyze-config.ts:204
}
}
const normalizeValue = (kind: ValueKind, value: unknown, key: string): unknown => {
const source = `${GITNEXUS_RC_FILENAME} "${key}"`;
switch (kind) {
case 'boolean':
if (typeof value !== 'boolean') {
throw new GitNexusRcError(`${source} must be a boolean (true/false).`);
}
return value;
case 'boolean-negate':
if (typeof value !== 'boolean') {
throw new GitNexusRcError(`${source} must be a boolean (true/false).`);
}
return !value;
case 'branch':
if (typeof value !== 'string') {
throw new GitNexusRcError(`${source} must be a string branch name.`);
}
return validateBranchName(value, source);
case 'path': {
if (typeof value !== 'string') {
throw new GitNexusRcError(`${source} must be a file or directory path.`);
}
const trimmed = value.trim();
if (!trimmed) {
throw new GitNexusRcError(`${source} must not be empty.`);
}
assertNoHiddenChars(trimmed, source);
return trimmed;
}
case 'string': {
if (typeof value !== 'string') {
throw new GitNexusRcError(`${source} must be a string.`);
}
const trimmed = value.trim();View on GitHub (pinned to ac9a4e9abd)