pbakaus/impeccable · error · Error
config.insertBefore or config.insertAfter (string) required
Error message
config.insertBefore or config.insertAfter (string) required
What it means
Thrown by validateConfig() in live-inject.mjs when neither cfg.insertBefore nor cfg.insertAfter is a string. The injector needs exactly one anchor telling it where in each matched file to insert the live snippet; with no string anchor it has no safe insertion point and refuses to proceed. The check is typeof cfg.insertBefore !== 'string' && typeof cfg.insertAfter !== 'string'.
Source
Thrown at skill/scripts/live-inject.mjs:466
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
// ---------------------------------------------------------------------------
const _running = process.argv[1];
if (_running?.endsWith('live-inject.mjs') || _running?.endsWith('live-inject.mjs/')) {
enterLiveRoot();
injectCli();
}View on GitHub (pinned to d14711ae3d)
Solutions
- Add exactly one anchor as a string: 'insertAfter' set to a literal HTML/JSX fragment like "<head>" or 'insertBefore' set to "</body>".
- If you set both, prefer keeping the single correct one and remove the other to avoid ambiguity (validateConfig allows both being strings but downstream logic prefers one).
- Confirm the anchor string actually appears in the target files, otherwise injection silently no-ops.
Example fix
// before
{
"files": ["src/**/*.html"],
"commentSyntax": "html"
}
// after
{
"files": ["src/**/*.html"],
"insertAfter": "<head>",
"commentSyntax": "html"
} Defensive patterns
Strategy: validation
Validate before calling
const anchor = typeof cfg.insertAfter === 'string' ? cfg.insertAfter
: typeof cfg.insertBefore === 'string' ? cfg.insertBefore
: null;
if (!anchor) throw new Error('config needs insertAfter or insertBefore as a string'); Type guard
function hasStringAnchor(cfg: any): cfg is { insertAfter: string } | { insertBefore: string } {
return typeof cfg?.insertAfter === 'string' || typeof cfg?.insertBefore === 'string';
} Prevention
- Always start from a known-good config template that includes one anchor.
- If you support multiple file shapes, generate one config per shape rather than one config with a regex anchor.
- Confirm the anchor string literally appears in target files via grep before running injection.
When it happens
Trigger: validateConfig runs on a config missing both 'insertBefore' and 'insertAfter', or where both are set to non-string values (null, undefined, number). Example: {files:[...], commentSyntax:'html'} with no anchor, or insertAfter: null.
Common situations: User copies a partial config template that omitted the anchor; renames the key (e.g. 'insertAfterHead') and forgets to update it; sets insertBefore to a RegExp object instead of its source string; deletes the anchor thinking the injector has a default (it does not).
Related errors
- config.json must be an object
- config.files (non-empty string array) required
- config.files must contain only non-empty strings
- config.exclude, if present, must be a string array
- config.exclude must contain only non-empty strings
AI-assisted analysis of pbakaus/impeccable@d14711ae3d (2026-08-13).
Data as JSON: /api/errors/7b782715d73ba754.
Report an issue: GitHub.