pbakaus/impeccable · error · Error

config.json must be an object

Error message

config.json must be an object

What it means

Thrown by validateConfig() in skill/scripts/live-inject.mjs when the parsed config.json is not a plain object (is null, an array, a primitive, or undefined after parse). The live-inject config must be an object so the subsequent files/exclude/insertAnchor fields can be validated; a non-object top level cannot satisfy them.

Source

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

      re += '[^/]';
      i += 1;
    } else if (/[.+^${}()|[\]\\]/.test(c)) {
      re += '\\' + c;
      i += 1;
    } else {
      re += c;
      i += 1;
    }
  }
  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') {

View on GitHub (pinned to d14711ae3d)

Solutions

  1. Make config.json a JSON object literal `{ ... }` at the top level.
  2. Validate with `jq 'type' config.json` — it must print "object".
  3. If building the config in code, ensure you serialize an object, not an array or scalar.

Example fix

// before
["src/app.tsx"]
// after
{
  "files": ["src/app.tsx"],
  "insertAfter": "</head>"
}
Defensive patterns

Strategy: type-guard

Validate before calling

function loadConfig(filePath) {
  const cfg = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
  if (!cfg || typeof cfg !== 'object' || Array.isArray(cfg)) {
    throw new Error(filePath + ' must be a JSON object');
  }
  return cfg;
}

Type guard

function isPlainObject(v) {
  return v !== null && typeof v === 'object' && !Array.isArray(v);
}

Prevention

When it happens

Trigger: A config.json whose top-level JSON value is an array, string, number, boolean, or null; or passing a non-object cfg programmatically to validateConfig.

Common situations: Editing config.json and accidentally wrapping it in an array, or leaving only a value; a generator that writes the wrong shape; JSON.parse returning null for content `null`.

Related errors


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