abhigyanpatwari/GitNexus · error · GitNexusRcError

${source} must be an array of strings.

Error message

${source} must be an array of strings.

What it means

Thrown by normalizeValue() in the 'string-array' case (for the fetchWrappers key) when the .gitnexusrc value is not a JSON array. Each entry is later interpolated into a RegExp for the cross-file HTTP consumer scan, so the shape must be a list of identifier-like strings.

Source

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

      // inside `gitnexus://repo/${name}/…` code spans, so a Markdown-significant
      // character would break those spans or inject emphasis/links/HTML into
      // agent-instruction content (#1996 tri-review P1). `_` is intentionally
      // allowed (legitimate in repo names; intraword `_` is not emphasis).
      // embeddingDevice (the other `string`-kind option) only ever holds a
      // fixed device token, so this guard never rejects a valid value there.
      if (/[`*[\]<>]/.test(trimmed)) {
        throw new GitNexusRcError(
          `${source} must not contain Markdown-significant characters (\` * [ ] < >).`,
        );
      }
      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").`,

View on GitHub (pinned to d540b00184)

Solutions

  1. Wrap the value in an array: "fetchWrappers": ["client.get"].
  2. Ensure the top-level value is a JSON array, not an object or string.
  3. If you have no wrappers to add, omit the key.

Example fix

// before
{ "fetchWrappers": "client.get" }

// after
{ "fetchWrappers": ["client.get"] }
Defensive patterns

Strategy: type-guard

Validate before calling

function assertStringArray(value: unknown, key: string): void {
  if (!Array.isArray(value)) {
    throw new Error(`${key} must be an array of strings`);
  }
}

Type guard

function isStringArray(value: unknown): value is unknown[] {
  return Array.isArray(value);
}

Prevention

When it happens

Trigger: Setting "fetchWrappers": "client.get" (a string, not an array), "fetchWrappers": { "a": 1 } (an object), "fetchWrappers": 42, or "fetchWrappers": null in .gitnexusrc.

Common situations: Writing a single wrapper as a bare string instead of a one-element array; confusing the array config shape with a scalar; a config generator that serialized a list as a single value.

Related errors


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