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

  1. Read the allowed-keys list printed in the error message and match one exactly.
  2. Correct the typo or remove the unknown key.
  3. 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

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


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/6205e8f5b5f9de8d. Report an issue: GitHub.