pbakaus/impeccable · error · Error

config.exclude, if present, must be a string array

Error message

config.exclude, if present, must be a string array

What it means

Thrown by validateConfig() in live-inject.mjs when a config.json contains an 'exclude' field that is not an Array. validateConfig guards every shape of the Impeccable Live injection config before any file mutation happens, so injection aborts up front rather than writing partial output. The check is Array.isArray(cfg.exclude) — anything else (object, string, number, null) trips it.

Source

Thrown at skill/scripts/live-inject.mjs:459

  }
  return new RegExp('^' + re + '$');
}

// ---------------------------------------------------------------------------
// Core operations
// ---------------------------------------------------------------------------

function validateConfig(cfg) {
  if (!cfg || typeof cfg !== 'object') throw new Error('config.json must be an object');
  if (!Array.isArray(cfg.files) || cfg.files.length === 0) {
    throw new Error('config.files (non-empty string array) required');
  }
  if (!cfg.files.every((f) => typeof f === 'string' && f.length > 0)) {
    throw new Error('config.files must contain only non-empty strings');
  }
  if (cfg.exclude !== undefined) {
    if (!Array.isArray(cfg.exclude)) {
      throw new Error('config.exclude, if present, must be a string array');
    }
    if (!cfg.exclude.every((f) => typeof f === 'string' && f.length > 0)) {
      throw new Error('config.exclude must contain only non-empty strings');
    }
  }
  if (typeof cfg.insertBefore !== 'string' && typeof cfg.insertAfter !== 'string') {
    throw new Error('config.insertBefore or config.insertAfter (string) required');
  }
  if (cfg.commentSyntax !== 'html' && cfg.commentSyntax !== 'jsx') {
    throw new Error("config.commentSyntax must be 'html' or 'jsx'");
  }
  if (cfg.cspChecked !== undefined && typeof cfg.cspChecked !== 'boolean') {
    throw new Error("config.cspChecked, if present, must be a boolean");
  }
}

// ---------------------------------------------------------------------------
// Auto-execute

View on GitHub (pinned to d14711ae3d)

Solutions

  1. Set 'exclude' to an array of glob strings, e.g. "exclude": ["**/*.test.js", "**/*.spec.js"].
  2. If you do not need exclusions, delete the 'exclude' key entirely (undefined is valid).
  3. Validate the file with a JSON schema or run the injector with a dry-run/validate mode before applying.

Example fix

// before
{
  "files": ["src/**/*.html"],
  "exclude": "**/*.test.html",
  "insertAfter": "<head>",
  "commentSyntax": "html"
}
// after
{
  "files": ["src/**/*.html"],
  "exclude": ["**/*.test.html"],
  "insertAfter": "<head>",
  "commentSyntax": "html"
}
Defensive patterns

Strategy: validation

Validate before calling

// Before calling validateConfig / the injector:
function isStringArray(v) {
  return Array.isArray(v) && v.every((x) => typeof x === 'string' && x.length > 0);
}
if (cfg.exclude !== undefined && !isStringArray(cfg.exclude)) {
  throw new Error('cfg.exclude must be a non-empty-string array');
}

Type guard

function isOptionalStringArray(v): v is string[] {
  return v === undefined || (Array.isArray(v) && v.every((x) => typeof x === 'string' && x.length > 0));
}

Prevention

When it happens

Trigger: validateConfig(cfg) is called with a parsed config.json whose 'exclude' key exists but is not an array — e.g. "exclude": "*.test.js" (string) or "exclude": {"glob": "*.test.js"} (object) or "exclude": null. The undefined case is intentionally allowed (the guard only runs when cfg.exclude !== undefined).

Common situations: Author hand-edits config.json and writes exclude as a single glob string instead of a one-element array; a generator/template emits exclude as an object; JSON5/JSON copy-paste from docs that used a shorthand notation. Often appears right after a user first discovers they need to exclude test fixtures from live injection.

Related errors


AI-assisted analysis of pbakaus/impeccable@d14711ae3d (2026-08-13). Data as JSON: /api/errors/9efc780988d6b9b9. Report an issue: GitHub.