{"record":{"id":"ca8ac4810b4e1f0d","repo":"abhigyanpatwari/GitNexus","slug":"source-must-be-an-array-of-strings","errorCode":null,"errorMessage":"${source} must be an array of strings.","messagePattern":"(.+?) must be an array of strings\\.","errorType":"validation","errorClass":"GitNexusRcError","httpStatus":null,"severity":"error","filePath":"gitnexus/src/cli/analyze-config.ts","lineNumber":256,"sourceCode":"      // inside `gitnexus://repo/${name}/…` code spans, so a Markdown-significant\n      // character would break those spans or inject emphasis/links/HTML into\n      // agent-instruction content (#1996 tri-review P1). `_` is intentionally\n      // allowed (legitimate in repo names; intraword `_` is not emphasis).\n      // embeddingDevice (the other `string`-kind option) only ever holds a\n      // fixed device token, so this guard never rejects a valid value there.\n      if (/[`*[\\]<>]/.test(trimmed)) {\n        throw new GitNexusRcError(\n          `${source} must not contain Markdown-significant characters (\\` * [ ] < >).`,\n        );\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\").`,","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/gitnexus/src/cli/analyze-config.ts#L238-L274","documentation":"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.","triggerScenarios":"Setting \"fetchWrappers\": \"client.get\" (a string, not an array), \"fetchWrappers\": { \"a\": 1 } (an object), \"fetchWrappers\": 42, or \"fetchWrappers\": null in .gitnexusrc.","commonSituations":"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.","solutions":["Wrap the value in an array: \"fetchWrappers\": [\"client.get\"].","Ensure the top-level value is a JSON array, not an object or string.","If you have no wrappers to add, omit the key."],"exampleFix":"// before\n{ \"fetchWrappers\": \"client.get\" }\n\n// after\n{ \"fetchWrappers\": [\"client.get\"] }","handlingStrategy":"type-guard","validationCode":"function assertStringArray(value: unknown, key: string): void {\n  if (!Array.isArray(value)) {\n    throw new Error(`${key} must be an array of strings`);\n  }\n}","typeGuard":"function isStringArray(value: unknown): value is unknown[] {\n  return Array.isArray(value);\n}","tryCatchPattern":null,"preventionTips":["Wrap single wrapper names in an array: [\"client.get\"].","Use a JSON array literal, never a comma-separated string.","Omit the key when there are no wrappers to add."],"tags":["validation","config","typescript","json"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}