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
- Check the exact path echoed by 'Reading configuration from:' and make that file exist and be readable (ls -l, run as the daemon user).
- If using --config, verify the path is correct and absolute (or relative to the install root as resolved by Filesystem::resolvePath).
- If relying on defaults, create phabricator/conf/aphlict/aphlict.custom.json copied from the shipped example/default so the default probe succeeds.
- 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
- Pass an absolute --config path in systemd/launch scripts to avoid cwd-dependent resolution.
- Ensure conf/aphlict/aphlict.custom.json exists (copy from the shipped default) on fresh installs.
- Run daemon launch as the user that owns/reads the config; verify with ls -l and sudo -u <user> cat.
- Lint deploy checklists with a simple file_exists + is_readable assertion on the config path.
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
- Specify a user to notify with "--user".
- No user with username "%s" exists.
- Specify a message to send with "--message".
- Configuration file does not specify any client servers. This
- Configuration file does not specify any administrative serve
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/416c25ea157eaf6c.
Report an issue: GitHub.