abhigyanpatwari/GitNexus · error · GitNexusRcError
Unknown key "${key}" in ${GITNEXUS_RC_FILENAME}. ${ALLOWED_K
Error message
Unknown key "${key}" in ${GITNEXUS_RC_FILENAME}. ${ALLOWED_KEYS_HINT} What it means
`.gitnexusrc` contains a top-level (or nested `analyze`) key that is not in the allowed KEY_SPECS set. GitNexus fails closed so a typo like `skipAgentMd` never silently no-ops. The error message appends ALLOWED_KEYS_HINT, which lists every accepted key plus the nested `analyze` object.
Source
Thrown at gitnexus/src/cli/analyze-config.ts:347
* Normalize one level (flat top-level or the nested `analyze` block) into a
* partial `AnalyzeOptions`. Rejects unknown keys and two aliases that configure
* the same option at the same level.
*/
const normalizeLevel = (
obj: Record<string, unknown>,
{ allowNestedKey }: { allowNestedKey: boolean },
): Partial<AnalyzeOptions> => {
const out: Partial<AnalyzeOptions> = {};
const setBy = new Map<keyof AnalyzeOptions, string>();
for (const [key, value] of Object.entries(obj)) {
if (allowNestedKey && key === NESTED_KEY) continue; // handled separately
// `Object.hasOwn`, not a truthiness check: a plain-object lookup like
// `KEY_SPECS["__proto__"]` returns an inherited member (Object.prototype,
// truthy) and would slip past `if (!spec)`, hitting the wrong error branch
// instead of the documented "Unknown key" message (#1996 tri-review P3).
if (!Object.hasOwn(KEY_SPECS, key)) {
throw new GitNexusRcError(
`Unknown key "${key}" in ${GITNEXUS_RC_FILENAME}. ${ALLOWED_KEYS_HINT}`,
);
}
const spec = KEY_SPECS[key];
const prev = setBy.get(spec.target);
if (prev && prev !== key) {
throw new GitNexusRcError(
`${GITNEXUS_RC_FILENAME}: "${prev}" and "${key}" both configure the same option; set only one.`,
);
}
setBy.set(spec.target, key);
(out as Record<string, unknown>)[spec.target] = normalizeValue(spec.kind, value, key);
}
return out;
};
/**View on GitHub (pinned to d540b00184)
Solutions
- Read the allowed-keys list printed in the error message and match one exactly.
- Correct the typo or remove the unknown key.
- If upgrading, check the changelog for renamed keys (e.g. alias consolidations).
Example fix
// before "skipAgentMd": true // after "skipAgentsMd": true
Defensive patterns
Strategy: validation
Validate before calling
const ALLOWED = ['defaultBranch','branch','skipAgentsMd','skipContextFiles','skipAiContext','skipSkills','pdg','indexOnly','stats','noStats','embeddings','dropEmbeddings','name','allowDuplicateName','maxFileSize','workerTimeout','walCheckpointThreshold','workers','embeddingThreads','embeddingBatchSize','embeddingSubBatchSize','embeddingDevice','fetchWrappers','embeddingBaseUrl','embeddingModel','analyze'];
for (const k of Object.keys(cfg)) {
if (!ALLOWED.includes(k)) throw new Error('Unknown key: ' + k);
} Prevention
- Read the allowed-keys hint printed by the error before adding a new key.
- After an upgrade, check the changelog for renamed keys.
- Lint .gitnexusrc against the allowed set in CI.
When it happens
Trigger: A typo such as { "skipAgentMd": true } (should be `skipAgentsMd`); a removed/renamed key from an older version; a key belonging to a different tool copy-pasted in.
Common situations: Typos after an upgrade; copy-pasting from outdated docs or another repo's config; using a CLI flag name verbatim as a config key when the accepted name differs.
Related errors
- ${source} entry "${trimmed}" must be an identifier or member
- ${source} must list at least one string.
- ${source} must be a finite number.
- ${source} must be a number or numeric string.
- ${source} must be true/false or a non-negative integer (node
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/6205e8f5b5f9de8d.
Report an issue: GitHub.