abhigyanpatwari/GitNexus · error · GitNexusRcError

entries must not be empty.

Error message

${source} entries must not be empty.

What it means

The .gitnexusrc string-array validator trims each element of 'fetchWrappers' and throws when an element is empty after trimming. Empty names cannot map to any function wrapper, so the shared normalizer rejects them instead of silently skipping.

Solutions

  1. Remove or fill in the blank entry so every element trims to a non-empty identifier
  2. Confirm with a quick check: every element matches /^[A-Za-z_$][A-Za-z0-9_$.]*$/ after trim
  3. Add a pre-commit or CI hook that rejects empty strings in fetchWrappers

Example fix

// before (.gitnexusrc)
{"fetchWrappers": ["client.get", ""]}
// after
{"fetchWrappers": ["client.get"]}
Defensive patterns

Strategy: validation

Validate before calling

const fw = rc.fetchWrappers ?? [];
if (fw.some((x: string) => x.trim() === '')) {
  throw new Error('fetchWrappers contains an empty entry');
}

Type guard

const hasNoBlankEntries = (v: string[]): boolean =>
  v.every((x) => x.trim().length > 0);

Try / catch

catch (err) {
  if (err instanceof GitNexusRcError && err.message.includes('must not be empty')) {
    // point the user at the blank entry in their rc file
  }
}

Prevention

When it happens

Trigger: {"fetchWrappers": ["client.get", " "]} or an explicit "" element, at the flat level or inside the nested "analyze" object.

Common situations: Leaving a placeholder entry ("" or "TODO") in a committed .gitnexusrc; merge artifacts that leave a stray comma-separated empty slot; copy-paste from docs that include an empty example element.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-08-20). Data as JSON: /api/errors/1be30bcbe124cd73. Report an issue: GitHub.

Appendix: source

Thrown at gitnexus/src/cli/analyze-config.ts:255

        );
      }
      return trimmed;
    }
    case 'string-array': {
      // Generic shared validator — `source` already names the config key, so
      // messages here stay key-agnostic (no fetch-wrapper coupling in the
      // shared normalizer; #1589/#1852 review F7).
      if (!Array.isArray(value)) {
        throw new GitNexusRcError(`${source} must be an array of strings.`);
      }
      const names: string[] = [];
      for (const item of value) {
        if (typeof item !== 'string') {
          throw new GitNexusRcError(`${source} entries must all be strings.`);
        }
        const trimmed = item.trim();
        if (!trimmed) {
          throw new GitNexusRcError(`${source} entries must not be empty.`);
        }
        assertNoHiddenChars(trimmed, source);
        // Values may be interpolated into a RegExp downstream. Restrict to
        // identifier / member-access shapes so a config value can never smuggle
        // regex metacharacters into a consumer.
        if (!/^[A-Za-z_$][A-Za-z0-9_$.]*$/.test(trimmed)) {
          throw new GitNexusRcError(
            `${source} entry "${trimmed}" must be an identifier or member name ` +
              `(letters, digits, _, $, . — e.g. "client.get").`,
          );
        }
        names.push(trimmed);
      }
      if (names.length === 0) {
        throw new GitNexusRcError(`${source} must list at least one string.`);
      }
      // De-duplicate and cap to a sane bound so a pathological config cannot
      // blow up the consumer scan's alternation.

View on GitHub (pinned to ac9a4e9abd)