phacility/phabricator · warning · PhutilArgumentUsageException

Specify an atomizer class with %s.

Error message

Specify an atomizer class with %s.

What it means

Diviner's `atomize` workflow turns source files into documentation atoms and needs an atomizer class to do the conversion. This PhutilArgumentUsageException is thrown at the top of execute() when the `--atomizer` flag is omitted, because the flag is declared without a default (DivinerAtomizeWorkflow.php:12-15). It is the CLI's standard usage-error signal: the process exits with a usage message instead of a stack trace.

Source

Thrown at src/applications/diviner/workflow/DivinerAtomizeWorkflow.php:39

          array(
            'name' => 'files',
            'wildcard' => true,
          ),
          array(
            'name' => 'ugly',
            'help' => pht('Produce ugly (but faster) output.'),
          ),
        ));
  }

  public function execute(PhutilArgumentParser $args) {
    $this->readBookConfiguration($args->getArg('book'));

    $console = PhutilConsole::getConsole();

    $atomizer_class = $args->getArg('atomizer');
    if (!$atomizer_class) {
      throw new PhutilArgumentUsageException(
        pht(
          'Specify an atomizer class with %s.',
          '--atomizer'));
    }

    $symbols = id(new PhutilSymbolLoader())
      ->setName($atomizer_class)
      ->setConcreteOnly(true)
      ->setAncestorClass('DivinerAtomizer')
      ->selectAndLoadSymbols();
    if (!$symbols) {
      throw new PhutilArgumentUsageException(
        pht(
          "Atomizer class '%s' must be a concrete subclass of %s.",
          $atomizer_class,
          'DivinerAtomizer'));
    }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Re-run with the flag: `diviner atomize --book docs/book.book --atomizer DivinerPHPAtomizer <files...>`
  2. Use a shipped concrete atomizer class such as DivinerPHPAtomizer unless you wrote your own
  3. If automating, check the flag is non-empty in your wrapper script before invoking `diviner atomize`

Example fix

# before
diviner atomize --book docs/book.book src/
# after
diviner atomize --book docs/book.book --atomizer DivinerPHPAtomizer src/
Defensive patterns

Strategy: validation

Validate before calling

$atomizer = $args->getArg('atomizer');
if (!strlen((string)$atomizer)) {
  // Do not invoke the workflow without an atomizer class.
  $args->printHelpAndExit();
}

Try / catch

try {
  $workflow->execute($args);
} catch (PhutilArgumentUsageException $ex) {
  // Usage errors are operator errors: show the message, exit non-zero.
  fwrite(STDERR, $ex->getMessage()."\n");
  exit(1);
}

Prevention

When it happens

Trigger: Running `diviner atomize` (or invoking DivinerAtomizeWorkflow::execute) with no `--atomizer` flag, i.e. $args->getArg('atomizer') is falsy. Any invocation that only passes `--book` and file wildcards hits it.

Common situations: Running Diviner manually for the first time and copying a partial command from docs; scripts that assume DivinerPHPAtomizer is the implicit default (it is not, unlike `--publisher` on `generate`); CI jobs assembled from a template that dropped the flag.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/d2653ae4e68d7592. Report an issue: GitHub.