{"record":{"id":"cfd9c6902fd282e9","repo":"ast-grep/ast-grep","slug":"rulenotspecified","errorCode":"RuleNotSpecified","errorMessage":"RuleNotSpecified","messagePattern":"RuleNotSpecified","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/scan.rs","lineNumber":324,"sourceCode":"\nstruct ScanStdin {\n  rules: Vec<RuleConfig<SgLang>>,\n  // TODO: remove this\n  error_count: AtomicUsize,\n  max_diagnostics_shown: Option<usize>,\n}\nimpl ScanStdin {\n  fn try_new(arg: ScanArg) -> Result<Self> {\n    let overwrite = RuleOverwrite::new(&arg.overwrite)?;\n    let global_rules = Default::default();\n    let rules = if let Some(path) = &arg.rule {\n      read_rule_file(path, &global_rules).and_then(|configs| overwrite.process_configs(configs))?\n    } else if let Some(text) = &arg.inline_rules {\n      let configs = from_yaml_string(text, &global_rules)\n        .with_context(|| EC::ParseRule(\"INLINE_RULES\".into()))?;\n      overwrite.process_configs(configs)?\n    } else {\n      return Err(anyhow::anyhow!(EC::RuleNotSpecified));\n    };\n    Ok(Self {\n      rules,\n      error_count: AtomicUsize::new(0),\n      max_diagnostics_shown: arg.max_results.map(usize::from),\n    })\n  }\n}\n\nimpl Worker for ScanStdin {\n  fn consume_items<P: Printer>(\n    &self,\n    items: Items<P::Processed>,\n    mut printer: P,\n  ) -> Result<ExitCode> {\n    printer.before_print()?;\n    for item in items {\n      printer.process(item)?;","sourceCodeStart":306,"sourceCodeEnd":342,"githubUrl":"https://github.com/ast-grep/ast-grep/blob/fc2b1530db74de49131b725221de98036a552a9f/crates/cli/src/scan.rs#L306-L342","documentation":"Thrown from ScanWorker::try_new when no rules could be located: the CLI was invoked as `sg scan` without a --rule/-r flag, without --inline-rules, and without any rule file path or inline rule text. ast-grep requires at least one rule source to construct the scan worker.","triggerScenarios":"Calling `sg scan` with neither `--rule <path>`, `--inline-rules <yaml>`, nor a rule file argument such that both `arg.rule_file` and `arg.inline_rules` are None in try_new.","commonSituations":"Forgetting -r when scanning ad hoc; running scan from a directory without sgconfig.yml while relying on implicit rule discovery; CI scripts dropping the rule flag during refactoring.","solutions":["Pass a rule: `sg scan -r my-rule.yml`","Or provide YAML directly: `sg scan --inline-rules 'id: x; language: js; rule: {pattern: foo}'`","Or create an `sgconfig.yml` with a `ruleDirs` entry and run from the project root","Check shell quoting so the flags are not swallowed"],"exampleFix":"// before\nsg scan ./src\n// after\nsg scan -r rules/no-console.yml ./src","handlingStrategy":"validation","validationCode":"if (!ruleFile && !inlineRules && !fs.existsSync('sgconfig.yml')) throw new Error('sg scan needs -r, --inline-rules, or sgconfig.yml');","typeGuard":null,"tryCatchPattern":"try { scan(args) } catch (e) { if (/RuleNotSpecified/.test(String(e))) { console.error('Provide -r <file> or --inline-rules'); process.exit(2); } throw e }","preventionTips":["Always run scan from the project root containing sgconfig.yml","Add the -r flag to scripts and CI templates","Keep an sgconfig.yml with ruleDirs in every repo"],"tags":["cli","ast-grep","configuration","missing-argument"],"backgroundTag":"missing-required-config","analyzedSha":"fc2b1530db74de49131b725221de98036a552a9f","analyzedAt":"2026-09-05T18:06:27.540Z","contentChangedAt":"2026-09-05T18:06:27.540Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}