pbakaus/impeccable · error · Error

${flag} requires a glob, got the flag ${glob}

Error message

${flag} requires a glob, got the flag ${glob}

What it means

Thrown by requireGlob() when the value supplied to --file/--files starts with `--`, i.e. the next token is itself a flag rather than a glob. Impeccable rejects this because an older parser consumed the following flag as the file scope, stored a junk scope like ["--reason"], and reported success — a silent no-op.

Source

Thrown at skill/scripts/hook-admin.mjs:639

  if (!glob) throw new Error(`Pass a glob, e.g. ${IMPECCABLE_COMMAND} hooks ignore-file "src/legacy/**"`);
  const config = mergeDetectorConfig(readRawDetectorConfig(cwd, { local: parsed.local }));
  if (!config.ignoreFiles.includes(glob)) config.ignoreFiles.push(glob);
  const target = writeDetectorConfig(cwd, config, { local: parsed.local });
  const scope = parsed.local ? 'local detector.ignoreFiles' : 'shared detector.ignoreFiles';
  return `Added "${glob}" to ${scope} (${path.relative(cwd, target) || target}). Current: ${config.ignoreFiles.join(', ')}`;
}

// An empty glob used to be dropped by filter(Boolean), so `--file=` reported
// success and wrote an entry with no files: the user asked to scope a rule to one
// file and silently got the project-wide suppression instead. Refuse it.
function requireGlob(raw, flag) {
  const glob = String(raw ?? '').trim();
  if (!glob) throw new Error(`${flag} requires a non-empty glob`);
  // A following flag is not a glob. `--file --reason "why"` consumed `--reason`
  // as the scope and left the reason text to fold into the value, storing
  // value="* why" files=["--reason"] and reporting success. Same silent-no-op
  // class as an unknown flag folding into the value; refuse it the same way.
  if (glob.startsWith('--')) throw new Error(`${flag} requires a glob, got the flag ${glob}`);
  return glob;
}

function parseIgnoreValueArgs(args) {
  const positionals = [];
  const files = [];
  let shared = false;
  let local = false;
  let reason = '';

  for (let i = 0; i < args.length; i++) {
    const arg = String(args[i] || '');
    if (arg === '--shared') {
      shared = true;
    } else if (arg === '--local') {
      local = true;
    } else if (arg === '--reason') {
      const chunks = [];

View on GitHub (pinned to d14711ae3d)

Solutions

  1. Put an actual glob between --file and the next flag: `--file "src/widget.css" --reason "why"`.
  2. Quote the glob and place it immediately after --file so the parser cannot grab the following flag.
  3. Use the `--file=<glob>` equals form, which cannot swallow the next token.

Example fix

// before
impeccable hooks ignore-value overused-font Inter --file --reason "brand lock"
// after
impeccable hooks ignore-value overused-font Inter --file "src/widget.css" --reason "brand lock"
Defensive patterns

Strategy: validation

Validate before calling

// Reject a flag-like value before passing it as a glob.
const glob = nextToken;
if (typeof glob !== 'string' || glob.startsWith('--')) {
  throw new Error('Expected a file glob, got a flag: ' + glob);
}

Type guard

function isGlobNotFlag(v) {
  return typeof v === 'string' && v.trim() !== '' && !v.startsWith('--');
}

Prevention

When it happens

Trigger: `impeccable hooks ignore-value <rule> <value> --file --reason "why"` (--reason eaten as the glob), or any `--file --<anything>` where the next token begins with `--`. Also `--file=--shared` style.

Common situations: Reordering flags and forgetting the glob value, or a script that appends `--file` conditionally but the value variable is itself a flag string.

Related errors


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