abhigyanpatwari/GitNexus · error · GitNexusRcError
${GITNEXUS_RC_FILENAME} is not valid JSON: ${(err as Error).
Error message
${GITNEXUS_RC_FILENAME} is not valid JSON: ${(err as Error).message}. Expected a JSON object such as {"defaultBranch": "develop", "skipContextFiles": true}. What it means
`.gitnexusrc` was read and a leading UTF-8 BOM was already stripped, but `JSON.parse` still failed — genuine JSON syntax error. The error appends Node's parse message and a correct example object so the fix is obvious. All keys must be double-quoted, no trailing commas, no comments.
Source
Thrown at gitnexus/src/cli/analyze-config.ts:392
let raw: string;
try {
raw = fs.readFileSync(filePath, 'utf-8');
} catch (err) {
if ((err as NodeJS.ErrnoException)?.code === 'ENOENT') return undefined;
throw new GitNexusRcError(`Could not read ${GITNEXUS_RC_FILENAME}: ${(err as Error).message}`);
}
// Strip a leading UTF-8 BOM: Node's 'utf-8' decode keeps it, and JSON.parse
// then fails with a confusing "Unexpected token" on an otherwise-valid file
// (#1996 tri-review). Only one leading BOM is stripped; in-string control
// rejection still applies to the parsed values.
if (raw.charCodeAt(0) === 0xfeff) raw = raw.slice(1);
let parsed: unknown;
try {
parsed = JSON.parse(raw);
} catch (err) {
throw new GitNexusRcError(
`${GITNEXUS_RC_FILENAME} is not valid JSON: ${(err as Error).message}. ` +
`Expected a JSON object such as {"defaultBranch": "develop", "skipContextFiles": true}.`,
);
}
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
throw new GitNexusRcError(`${GITNEXUS_RC_FILENAME} must contain a JSON object.`);
}
const obj = parsed as Record<string, unknown>;
const flat = normalizeLevel(obj, { allowNestedKey: true });
let nested: Partial<AnalyzeOptions> = {};
if (Object.prototype.hasOwnProperty.call(obj, NESTED_KEY)) {
const nestedRaw = obj[NESTED_KEY];
if (nestedRaw === null || typeof nestedRaw !== 'object' || Array.isArray(nestedRaw)) {
throw new GitNexusRcError(`${GITNEXUS_RC_FILENAME} "${NESTED_KEY}" must be a JSON object.`);
}View on GitHub (pinned to d540b00184)
Solutions
- Validate the file standalone: node -e 'JSON.parse(require("fs").readFileSync(".gitnexusrc","utf8"))'.
- Double-quote all keys and string values; remove trailing commas and comments.
- Re-save as UTF-8 without BOM (a leading BOM is already tolerated, but strip it to be safe).
Example fix
// before
{defaultBranch: "develop",}
// after
{"defaultBranch": "develop"} Defensive patterns
Strategy: validation
Validate before calling
// Validate JSON before running gitnexus analyze
const raw = require('node:fs').readFileSync('.gitnexusrc', 'utf8');
JSON.parse(raw); // throws with a precise location if invalid Try / catch
try {
loadAnalyzeConfig(repoRoot);
} catch (e) {
if (e instanceof GitNexusRcError && e.message.includes('is not valid JSON')) {
// run `node -e 'JSON.parse(...)'` for the caret position
}
throw e;
} Prevention
- Use double-quoted keys, no trailing commas, no comments.
- Run `node -e JSON.parse` on .gitnexusrc in pre-commit.
When it happens
Trigger: Trailing comma { "a": 1, }; unquoted keys { a: 1 }; single-quoted values { 'a': 'b' }; a // comment; a stray control character inside a string.
Common situations: Hand-editing and treating the file like a JS object literal; copy-pasting from a JS source or README that used unquoted keys; JSON5/JSONC syntax in a strict-JSON file.
Related errors
- ${GITNEXUS_RC_FILENAME} must contain a JSON object.
- ${GITNEXUS_RC_FILENAME} "${NESTED_KEY}" must be a JSON objec
- ${source} must be a boolean (true/false).
- ${source} must be a string.
- ${source} must be an array of strings.
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/08693cedf45d3187.
Report an issue: GitHub.