{"record":{"id":"1339fa8996f92152","repo":"pbakaus/impeccable","slug":"flag-requires-a-non-empty-glob","errorCode":null,"errorMessage":"${flag} requires a non-empty glob","messagePattern":"(.+?) requires a non-empty glob","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"skill/scripts/hook-admin.mjs","lineNumber":634,"sourceCode":"}\n\nfunction addIgnoreFile(cwd, args) {\n  const parsed = parseIgnoreFileArgs(args);\n  const glob = parsed.glob;\n  if (!glob) throw new Error(`Pass a glob, e.g. ${IMPECCABLE_COMMAND} hooks ignore-file \"src/legacy/**\"`);\n  const config = mergeDetectorConfig(readRawDetectorConfig(cwd, { local: parsed.local }));\n  if (!config.ignoreFiles.includes(glob)) config.ignoreFiles.push(glob);\n  const target = writeDetectorConfig(cwd, config, { local: parsed.local });\n  const scope = parsed.local ? 'local detector.ignoreFiles' : 'shared detector.ignoreFiles';\n  return `Added \"${glob}\" to ${scope} (${path.relative(cwd, target) || target}). Current: ${config.ignoreFiles.join(', ')}`;\n}\n\n// An empty glob used to be dropped by filter(Boolean), so `--file=` reported\n// success and wrote an entry with no files: the user asked to scope a rule to one\n// file and silently got the project-wide suppression instead. Refuse it.\nfunction requireGlob(raw, flag) {\n  const glob = String(raw ?? '').trim();\n  if (!glob) throw new Error(`${flag} requires a non-empty glob`);\n  // A following flag is not a glob. `--file --reason \"why\"` consumed `--reason`\n  // as the scope and left the reason text to fold into the value, storing\n  // value=\"* why\" files=[\"--reason\"] and reporting success. Same silent-no-op\n  // class as an unknown flag folding into the value; refuse it the same way.\n  if (glob.startsWith('--')) throw new Error(`${flag} requires a glob, got the flag ${glob}`);\n  return glob;\n}\n\nfunction parseIgnoreValueArgs(args) {\n  const positionals = [];\n  const files = [];\n  let shared = false;\n  let local = false;\n  let reason = '';\n\n  for (let i = 0; i < args.length; i++) {\n    const arg = String(args[i] || '');\n    if (arg === '--shared') {","sourceCodeStart":616,"sourceCodeEnd":652,"githubUrl":"https://github.com/pbakaus/impeccable/blob/f88b2837a7d7c3182e46307bbbb091a1ed547571/skill/scripts/hook-admin.mjs#L616-L652","documentation":"Thrown by requireGlob when a --file/--files flag for `hooks ignore-value` receives an empty value after trimming. Historically filter(Boolean) dropped the empty entry, so `--file=` reported success but stored a value ignore with no file scope — the user asked to scope a suppression and silently got the broader one. The guard makes that failure loud.","triggerScenarios":"`hooks ignore-value low-contrast \"#eee\" --file=` (empty equals-value); `--file \"\"` (explicitly empty string); a shell variable that expands to nothing: `--file \"$SCOPE\"` with SCOPE unset.","commonSituations":"Scripted invocations interpolating optional variables that are empty; hand-typed commands where the glob was forgotten after the =.","solutions":["Provide a real glob: `--file \"src/widget.js\"` or `--file=\"src/widget.js\"`.","Drop the --file flag entirely if you want the ignore to apply across the whole config's scope.","In scripts, skip emitting the flag when the variable is empty rather than passing an empty value."],"exampleFix":"# before\nimpeccable hooks ignore-value low-contrast \"#eee\" --file=\n\n# after\nimpeccable hooks ignore-value low-contrast \"#eee\" --file \"src/widget.css\"","handlingStrategy":"validation","validationCode":"function fileFlag(scope) {\n  const v = String(scope ?? '').trim();\n  return v ? ['--file', v] : [];   // omit the flag instead of passing an empty value\n}","typeGuard":"function isNonEmptyGlob(v) {\n  return typeof v === 'string' && v.trim().length > 0 && !v.trim().startsWith('--');\n}","tryCatchPattern":null,"preventionTips":["Never emit --file= with nothing after the equals; conditionally omit the whole flag instead.","Interpolate optional scope variables only after checking they are non-empty."],"tags":["cli","empty-argument","hook-admin","ignore-value","glob"],"backgroundTag":"missing-flag-value","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"}