{"record":{"id":"1be30bcbe124cd73","repo":"abhigyanpatwari/GitNexus","slug":"source-entries-must-not-be-empty","errorCode":null,"errorMessage":"${source} entries must not be empty.","messagePattern":"(.+?) entries must not be empty\\.","errorType":"validation","errorClass":"GitNexusRcError","httpStatus":null,"severity":"error","filePath":"gitnexus/src/cli/analyze-config.ts","lineNumber":265,"sourceCode":"        );\n      }\n      return trimmed;\n    }\n    case 'string-array': {\n      // Generic shared validator — `source` already names the config key, so\n      // messages here stay key-agnostic (no fetch-wrapper coupling in the\n      // shared normalizer; #1589/#1852 review F7).\n      if (!Array.isArray(value)) {\n        throw new GitNexusRcError(`${source} must be an array of strings.`);\n      }\n      const names: string[] = [];\n      for (const item of value) {\n        if (typeof item !== 'string') {\n          throw new GitNexusRcError(`${source} entries must all be strings.`);\n        }\n        const trimmed = item.trim();\n        if (!trimmed) {\n          throw new GitNexusRcError(`${source} entries must not be empty.`);\n        }\n        assertNoHiddenChars(trimmed, source);\n        // Values may be interpolated into a RegExp downstream. Restrict to\n        // identifier / member-access shapes so a config value can never smuggle\n        // regex metacharacters into a consumer.\n        if (!/^[A-Za-z_$][A-Za-z0-9_$.]*$/.test(trimmed)) {\n          throw new GitNexusRcError(\n            `${source} entry \"${trimmed}\" must be an identifier or member name ` +\n              `(letters, digits, _, $, . — e.g. \"client.get\").`,\n          );\n        }\n        names.push(trimmed);\n      }\n      if (names.length === 0) {\n        throw new GitNexusRcError(`${source} must list at least one string.`);\n      }\n      // De-duplicate and cap to a sane bound so a pathological config cannot\n      // blow up the consumer scan's alternation.","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/gitnexus/src/cli/analyze-config.ts#L247-L283","documentation":"Thrown by normalizeValue() in the 'string-array' case when an entry trims to empty. Empty entries would produce empty alternations in the downstream consumer-scan RegExp and add no value, so they are rejected to surface config mistakes rather than silently ignored.","triggerScenarios":"Setting \"fetchWrappers\": [\"\"], \"fetchWrappers\": [\"client.get\", \"   \"], or \"fetchWrappers\": [\"\", \"x\"] in .gitnexusrc.","commonSituations":"A trailing comma in a hand-written JSON array that produced an empty slot; a whitespace-only placeholder; a template that left empty strings for unfilled wrappers.","solutions":["Remove empty or whitespace-only entries from the array.","Provide real identifier-shaped strings (e.g. \"client.get\").","If you have no wrappers, omit the key entirely."],"exampleFix":"// before\n{ \"fetchWrappers\": [\"client.get\", \"\"] }\n\n// after\n{ \"fetchWrappers\": [\"client.get\"] }","handlingStrategy":"validation","validationCode":"function assertNoEmptyEntries(arr: string[], key: string): void {\n  for (const item of arr) {\n    if (typeof item !== 'string' || item.trim() === '') {\n      throw new Error(`${key} entries must not be empty`);\n    }\n  }\n}","typeGuard":"function hasNoEmptyEntries(value: unknown): boolean {\n  return Array.isArray(value) && value.every((v) => typeof v === 'string' && v.trim().length > 0);\n}","tryCatchPattern":null,"preventionTips":["Remove trailing commas and empty slots from hand-written JSON arrays.","Filter out empty/whitespace placeholders before committing.","Omit the fetchWrappers key entirely when there is nothing to add."],"tags":["validation","config"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}