{"record":{"id":"014f1f46c7f92bce","repo":"pbakaus/impeccable","slug":"config-files-non-empty-string-array-required","errorCode":null,"errorMessage":"config.files (non-empty string array) required","messagePattern":"config\\.files \\(non-empty string array\\) required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"plugin/skills/impeccable/scripts/live-inject.mjs","lineNumber":452,"sourceCode":"    } 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') {\n    throw new Error(\"config.commentSyntax must be 'html' or 'jsx'\");\n  }","sourceCodeStart":434,"sourceCodeEnd":470,"githubUrl":"https://github.com/pbakaus/impeccable/blob/d14711ae3d1a1dd62dee61a358d27f107c51ccd0/plugin/skills/impeccable/scripts/live-inject.mjs#L434-L470","documentation":"Second validateConfig() check: cfg.files must be a non-empty array. Fires when files is missing, is present but not an array (e.g. a string or object), or is an empty array []. The live-inject flow needs at least one HTML entry point to tag, so an empty list is treated as misconfiguration, not a no-op.","triggerScenarios":"config.json has no 'files' key; \"files\": \"index.html\" (string not array); \"files\": [] (empty); \"files\": {} (object). Each literal entry in files is later treated as a path or glob in resolveFiles(), so the array shape is mandatory.","commonSituations":"Setup wizard skipped the file-picker step; user deleted all entries thinking inject would auto-detect; mismerged config where 'files' became a single string; glob-only intent but written as a string instead of [\"**\\/*.html\"].","solutions":["Set config.files to a non-empty array of HTML entry-point paths or globs, e.g. [\"index.html\", \"**\\/*.html\"].","Re-run the live setup flow to regenerate the config with detected entry points.","If you genuinely want glob discovery, still wrap the pattern in an array: [\"src\\/**/*.html\"].","Validate with `node live-inject.mjs --check` after editing."],"exampleFix":"// before\n{ \"commentSyntax\": \"html\", \"insertBefore\": \"</head>\" }\n\n// after\n{\n  \"files\": [\"index.html\"],\n  \"commentSyntax\": \"html\",\n  \"insertBefore\": \"</head>\"\n}","handlingStrategy":"validation","validationCode":"function hasNonEmptyFiles(cfg) {\n  return Array.isArray(cfg?.files) && cfg.files.length > 0;\n}\nif (!hasNonEmptyFiles(cfg)) {\n  throw new Error('config.files must be a non-empty array of paths/globs');\n}","typeGuard":"/** Narrow cfg to one with a usable files array. */\nfunction hasFilesArray(cfg) {\n  return cfg != null && typeof cfg === 'object'\n    && Array.isArray(cfg.files) && cfg.files.length > 0;\n}","tryCatchPattern":"try {\n  validateConfig(cfg);\n} catch (err) {\n  if (/config\\.files/.test(err.message)) {\n    console.error('Fix config.files: ' + err.message);\n    // re-run setup to detect entry points\n    process.exit(1);\n  }\n  throw err;\n}","preventionTips":["Wrap even a single entry point in an array: [\"index.html\"].","Re-run live setup if you remove the last entry — an empty array is not a valid no-op.","Use globs inside the array (e.g. [\"**\\/*.html\"]) rather than a bare pattern string."],"tags":["live-inject","config","validation","json"],"backgroundTag":null,"analyzedSha":"d14711ae3d1a1dd62dee61a358d27f107c51ccd0","analyzedAt":"2026-08-13T00:52:25.771Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}