pbakaus/impeccable · error · Error

config.commentSyntax must be 'html' or 'jsx'

Error message

config.commentSyntax must be 'html' or 'jsx'

What it means

validateConfig() requires cfg.commentSyntax to be exactly 'html' or 'jsx'. There is no default: the field decides whether the injected block uses <!-- --> or {/* */ *} comment syntax, so an omitted or misspelled value is rejected rather than guessed. Any other string (or non-string) fails.

Solutions

  1. Set "commentSyntax": "html" for HTML/Astro-ish targets or "commentSyntax": "jsx" for JSX/TSX-style comments
  2. Lowercase the value — the comparison is exact
  3. For React/Next projects use 'jsx' even in .js files that contain JSX

Example fix

// before
"commentSyntax": "tsx"

// after
"commentSyntax": "jsx"
Defensive patterns

Strategy: validation

Validate before calling

const syntax = cfg.commentSyntax;
if (syntax !== 'html' && syntax !== 'jsx') {
  throw new TypeError(`config.commentSyntax must be 'html' or 'jsx' — got ${JSON.stringify(syntax)}`);
}

Type guard

const isSupportedCommentSyntax = (v) => v === 'html' || v === 'jsx';

Prevention

When it happens

Trigger: commentSyntax missing from the config; commentSyntax: "HTML" (case-sensitive); "js", "tsx", "ts", or "javascript" — none of the alternatives are accepted, only the literal 'html' and 'jsx'.

Common situations: JS/TS projects assuming a 'js' or 'ts' value; uppercase values from hand editing; configs generated from a form that labels the option differently.

Related errors


AI-assisted analysis of pbakaus/impeccable@f88b2837a7 (2026-08-18). Data as JSON: /api/errors/4c05b321b9154e69. Report an issue: GitHub.

Appendix: source

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

  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();
}

// Re-exported so long-standing importers (live.mjs, the adapter modules, the
// test suites) keep their entry points while the implementations live in

View on GitHub (pinned to f88b2837a7)