{"record":{"id":"2cc1f072b44d29f5","repo":"pbakaus/impeccable","slug":"config-json-must-be-an-object","errorCode":null,"errorMessage":"config.json must be an object","messagePattern":"config\\.json must be an object","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skill/scripts/live-inject.mjs","lineNumber":450,"sourceCode":"      re += '[^/]';\n      i += 1;\n    } else if (/[.+^${}()|[\\]\\\\]/.test(c)) {\n      re += '\\\\' + c;\n      i += 1;\n    } else {\n      re += c;\n      i += 1;\n    }\n  }\n  return new RegExp('^' + re + '$');\n}\n\n// ---------------------------------------------------------------------------\n// Core operations\n// ---------------------------------------------------------------------------\n\nfunction validateConfig(cfg) {\n  if (!cfg || typeof cfg !== 'object') throw new Error('config.json must be an object');\n  if (!Array.isArray(cfg.files) || cfg.files.length === 0) {\n    throw new Error('config.files (non-empty string array) required');\n  }\n  if (!cfg.files.every((f) => typeof f === 'string' && f.length > 0)) {\n    throw new Error('config.files must contain only non-empty strings');\n  }\n  if (cfg.exclude !== undefined) {\n    if (!Array.isArray(cfg.exclude)) {\n      throw new Error('config.exclude, if present, must be a string array');\n    }\n    if (!cfg.exclude.every((f) => typeof f === 'string' && f.length > 0)) {\n      throw new Error('config.exclude must contain only non-empty strings');\n    }\n  }\n  if (typeof cfg.insertBefore !== 'string' && typeof cfg.insertAfter !== 'string') {\n    throw new Error('config.insertBefore or config.insertAfter (string) required');\n  }\n  if (cfg.commentSyntax !== 'html' && cfg.commentSyntax !== 'jsx') {","sourceCodeStart":432,"sourceCodeEnd":468,"githubUrl":"https://github.com/pbakaus/impeccable/blob/f88b2837a7d7c3182e46307bbbb091a1ed547571/skill/scripts/live-inject.mjs#L432-L468","documentation":"validateConfig() in skill/scripts/live-inject.mjs guards every inject run: the parsed content of .impeccable/live/config.json must be a plain object before any other field is checked. JSON that parses to null, an array, a string, or a number fails this first check. The file drives script injection into the listed files, so a non-object root means the config was authored as the wrong kind of JSON document entirely.","triggerScenarios":"Running live-inject (directly or via the live flow that reads .impeccable/live/config.json) when the file's root is e.g. [\"src/**/*.html\"], \"config\", 1, or null. The `--check` flag prints whether the file exists and its content, confirming the shape.","commonSituations":"An agent hand-authoring the config on first live run emits the files array as the whole document; the file is truncated to a fragment by a partial write; a template placeholder string is left as the root.","solutions":["Rewrite .impeccable/live/config.json as an object containing the required keys: files (non-empty string array), insertBefore or insertAfter (string), commentSyntax ('html'|'jsx')","Run `node skill/scripts/live-inject.mjs --check` first to see the current content","Delete the file and re-run the Setup/live flow — it is created once per project when missing"],"exampleFix":"// .impeccable/live/config.json — before\n[\"src/**/*.html\"]\n\n// after\n{\n  \"files\": [\"src/**/*.html\"],\n  \"insertAfter\": \"</title>\",\n  \"commentSyntax\": \"html\"\n}","handlingStrategy":"validation","validationCode":"import fs from 'node:fs';\n\nconst raw = fs.readFileSync('.impeccable/live/config.json', 'utf-8');\nconst cfg = JSON.parse(raw); // throws first on broken JSON\nif (!cfg || typeof cfg !== 'object' || Array.isArray(cfg)) {\n  throw new TypeError('live inject config root must be a JSON object');\n}","typeGuard":"const isInjectConfigObject = (cfg) =>\n  !!cfg && typeof cfg === 'object' && !Array.isArray(cfg);","tryCatchPattern":null,"preventionTips":["Let the Setup flow generate .impeccable/live/config.json once; hand-edit conservatively afterwards","Run `node skill/scripts/live-inject.mjs --check` after any manual edit — it prints existence and content","Validate configs in CI with the same rules validateConfig() applies before shipping to the live flow"],"tags":["config","json","schema","live-inject"],"backgroundTag":"config-schema-validation","analyzedSha":"f88b2837a7d7c3182e46307bbbb091a1ed547571","analyzedAt":"2026-08-18T04:58:36.608Z","contentChangedAt":"2026-08-18T04:58:36.608Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}