phacility/phabricator · error · PhutilArgumentUsageException

Failed to read configuration file. %s

Error message

Failed to read configuration file. %s

What it means

Base class for Aphlict (notification server) management workflows fails while reading its JSON config: Filesystem::readFile($full_path) threw and the message is wrapped into a usage exception. The path is either the --config file given on the command line or the default candidate conf/aphlict/aphlict.custom.json / aphlict.default.json, where a missing default leaves $full_path pointing at a file that does not exist.

Source

Thrown at src/applications/aphlict/management/PhabricatorAphlictManagementWorkflow.php:58

      foreach ($try as $config) {
        $full_path = $root.'/'.$config;
        $show_path = $config;
        if (Filesystem::pathExists($full_path)) {
          break;
        }
      }
    }

    echo tsprintf(
      "%s\n",
      pht(
        'Reading configuration from: %s',
        $show_path));

    try {
      $data = Filesystem::readFile($full_path);
    } catch (Exception $ex) {
      throw new PhutilArgumentUsageException(
        pht(
          'Failed to read configuration file. %s',
          $ex->getMessage()));
    }

    try {
      $data = phutil_json_decode($data);
    } catch (Exception $ex) {
      throw new PhutilArgumentUsageException(
        pht(
          'Configuration file is not properly formatted JSON. %s',
          $ex->getMessage()));
    }

    try {
      PhutilTypeSpec::checkMap(
        $data,
        array(

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Check the exact path echoed by 'Reading configuration from:' and make that file exist and be readable (ls -l, run as the daemon user).
  2. If using --config, verify the path is correct and absolute (or relative to the install root as resolved by Filesystem::resolvePath).
  3. If relying on defaults, create phabricator/conf/aphlict/aphlict.custom.json copied from the shipped example/default so the default probe succeeds.
  4. The wrapped %s carries the underlying reason (No such file / permission denied) - read it to pick between path vs permissions fixes.
Defensive patterns

Strategy: validation

Validate before calling

$full_path = Filesystem::resolvePath($config_file);
if (!Filesystem::pathExists($full_path)) {
  throw new Exception("Aphlict config not found at {$full_path}.");
}
if (!is_readable($full_path)) {
  throw new Exception("Aphlict config {$full_path} is not readable by this user.");
}
// Safe to hand off to the management workflow.

Try / catch

try {
  // launch aphlict workflow
} catch (PhutilArgumentUsageException $ex) {
  if (preg_match('/Failed to read configuration file/', $ex->getMessage())) {
    // The wrapped %s is the underlying Filesystem error: missing file vs permissions.
    // Fix path/ownership, then retry once; do not loop.
  }
  throw $ex;
}

Prevention

When it happens

Trigger: Passing --config /path/that/does/not/exist.json; the file existing but unreadable to the web/CLI user (permissions); the default conf/aphlict/ directory lacking both aphlict.custom.json and aphlict.default.json so the fallback path is used and read fails.

Common situations: Fresh checkout or partial deploy where conf/aphlict defaults were never installed; permissions tightened so the daemon user cannot read the JSON; typo in the --config path in systemd unit or launch scripts.

Related errors


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