abhigyanpatwari/GitNexus · error · GitNexusRcError
" " must be a JSON object.
Error message
${GITNEXUS_RC_FILENAME} "${NESTED_KEY}" must be a JSON object. What it means
The optional nested "analyze" block in .gitnexusrc must itself be a JSON object. If the key exists but its value is an array, null, or a scalar, loadAnalyzeConfig throws before normalizing that level's keys.
Solutions
- Make the block an object of allowed keys: {"analyze": {"workers": 8}}
- If you meant flags-as-string, translate them into real keys instead
- Empty nested block {} is legal but pointless — either populate it or drop it
Example fix
// before (.gitnexusrc)
{"analyze": "--workers 8"}
// after
{"analyze": {"workers": 8}} Defensive patterns
Strategy: type-guard
Validate before calling
if (rc.analyze !== undefined && (rc.analyze === null || typeof rc.analyze !== 'object' || Array.isArray(rc.analyze))) {
throw new Error('.gitnexusrc "analyze" must be a JSON object of option keys');
} Type guard
const isNestedAnalyzeBlock = (v: unknown): v is Record<string, unknown> => v !== null && typeof v === 'object' && !Array.isArray(v);
Try / catch
catch (err) {
if (err instanceof GitNexusRcError && err.message.includes('"analyze" must be a JSON object')) {
// convert flag strings into real keys inside the block
}
} Prevention
- The "analyze" block holds option keys, not a CLI flag string
- Mirror the same key set as the flat level inside it
When it happens
Trigger: {"analyze": []}, {"analyze": null}, or {"analyze": "workers=4"} in .gitnexusrc; also a nested block mistakenly placed two levels deep so the value ends up a string.
Common situations: Assuming "analyze" takes a string of CLI flags; scaffolding with an empty array; merging configs where the nested object got replaced by a list.
Related errors
- must contain a JSON object.
- entries must all be strings.
- is not valid JSON: . Expected a JSON object such as .
- : " " and " " both configure the same option; set only one.
- entries must not be empty.
AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-08-20).
Data as JSON: /api/errors/c297f8dfd0921d09.
Report an issue: GitHub.
Appendix: source
Thrown at gitnexus/src/cli/analyze-config.ts:417
} 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.`);
}
nested = normalizeLevel(nestedRaw as Record<string, unknown>, { allowNestedKey: false });
}
// Nested `analyze` block overrides flat top-level keys for the same option.
return { ...flat, ...nested };
}
/**
* Merge CLI options over `.gitnexusrc` defaults. CLI wins whenever it provides a
* value — including an explicit `false` (so an explicit CLI off-switch beats a
* config `true`). Config fills only the genuinely-unset (`undefined`) options.
*
* `stats` is special: Commander always materializes it (`true` by default,
* `false` only when `--no-stats` is passed), so plain `??` can't tell "default
* on" from "explicitly on". The rule is: a passed `--no-stats` (`stats: false`)
* always wins; otherwise the config value applies. There is intentionally no
* `--stats` counter-flag, so config can only turn stats off, not force it backView on GitHub (pinned to ac9a4e9abd)