{"record":{"id":"79f1a4dc946c5eaa","repo":"phacility/phabricator","slug":"specify-one-or-more-files-to-atomize","errorCode":null,"errorMessage":"Specify one or more files to atomize.","messagePattern":"Specify one or more files to atomize\\.","errorType":"console","errorClass":"Exception","httpStatus":null,"severity":"warning","filePath":"src/applications/diviner/workflow/DivinerAtomizeWorkflow.php","lineNumber":62,"sourceCode":"\n    $symbols = id(new PhutilSymbolLoader())\n      ->setName($atomizer_class)\n      ->setConcreteOnly(true)\n      ->setAncestorClass('DivinerAtomizer')\n      ->selectAndLoadSymbols();\n    if (!$symbols) {\n      throw new PhutilArgumentUsageException(\n        pht(\n          \"Atomizer class '%s' must be a concrete subclass of %s.\",\n          $atomizer_class,\n          'DivinerAtomizer'));\n    }\n\n    $atomizer = newv($atomizer_class, array());\n\n    $files = $args->getArg('files');\n    if (!$files) {\n      throw new Exception(pht('Specify one or more files to atomize.'));\n    }\n\n    $file_atomizer = new DivinerFileAtomizer();\n\n    foreach (array($atomizer, $file_atomizer) as $configure) {\n      $configure->setBook($this->getConfig('name'));\n    }\n\n    $group_rules = array();\n    foreach ($this->getConfig('groups', array()) as $group => $spec) {\n      $include = (array)idx($spec, 'include', array());\n      foreach ($include as $pattern) {\n        $group_rules[$pattern] = $group;\n      }\n    }\n\n    $all_atoms = array();\n    $context = array(","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/diviner/workflow/DivinerAtomizeWorkflow.php#L44-L80","documentation":"Diviner's atomize workflow takes the files to process as wildcard (positional) arguments. After the atomizer is constructed, execute() reads $args->getArg('files') and throws this plain Exception when the list is empty. Unlike the neighboring errors it is a generic Exception, not PhutilArgumentUsageException, so it surfaces with a stack trace rather than a usage message.","triggerScenarios":"Invoking `diviner atomize --book ... --atomizer ...` with no trailing file paths, or with a wildcard that your shell expanded to nothing (e.g. `src/*.php` in an empty directory).","commonSituations":"Shell glob failing to match (empty dir, wrong cwd, or quotes around the glob preventing expansion); CI jobs that pass a variable which is empty; running atomize from a directory that does not contain the sources you meant.","solutions":["Append one or more file paths after the flags: `diviner atomize --book b.book --atomizer DivinerPHPAtomizer src/*.php`","Check the glob actually matches: run `ls src/*.php` in the same directory and cwd","If passing a variable in a script, fail fast when it is empty instead of running Diviner"],"exampleFix":"# before\ndiviner atomize --book docs/book.book --atomizer DivinerPHPAtomizer\n# after\ndiviner atomize --book docs/book.book --atomizer DivinerPHPAtomizer src/**/*.php","handlingStrategy":"validation","validationCode":"$files = $args->getArg('files');\nif (!$files) {\n  // Refuse to run atomize with an empty file list.\n  $args->printHelpAndExit();\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["In scripts, check the file list variable is non-empty before running diviner","Verify shell globs match by echoing the expanded list in the same cwd","Quote wildcards only when you want Diviner to receive them literally"],"tags":["diviner","cli","missing-argument","phabricator"],"backgroundTag":"missing-cli-argument","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}