phacility/phabricator · critical · PhutilProxyException

Configuration file "%s" exists and is readable, but the cont

Error message

Configuration file "%s" exists and is readable, but the content is not valid JSON. You may have edited this file manually and introduced a syntax error by mistake. Correct the file syntax to continue.

What it means

After successfully reading conf/local/local.json, PhabricatorConfigLocalSource decodes it with phutil_json_decode(); if the content is not valid JSON (trailing comma, smart quotes, comment lines, truncation), the PhutilJSONParserException is proxied with this message. Phabricator refuses to guess a partial config, so the invalid file halts config loading instance-wide.

Source

Thrown at src/infrastructure/env/PhabricatorConfigLocalSource.php:42

    if (!Filesystem::pathExists($path)) {
      return array();
    }

    try {
      $data = Filesystem::readFile($path);
    } catch (FilesystemException $ex) {
      throw new PhutilProxyException(
        pht(
          'Configuration file "%s" exists, but could not be read.',
          $path),
        $ex);
    }

    try {
      $result = phutil_json_decode($data);
    } catch (PhutilJSONParserException $ex) {
      throw new PhutilProxyException(
        pht(
          'Configuration file "%s" exists and is readable, but the content '.
          'is not valid JSON. You may have edited this file manually and '.
          'introduced a syntax error by mistake. Correct the file syntax '.
          'to continue.',
          $path),
        $ex);
    }

    return $result;
  }

  private function saveConfig() {
    $config = $this->getSource()->getAllKeys();
    $json = new PhutilJSON();
    $data = $json->encodeFormatted($config);
    Filesystem::writeFile($this->getConfigPath(), $data);
  }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Validate and fix the file: php -r 'json_decode(file_get_contents("conf/local/local.json")); echo json_last_error_msg();' then correct the reported position (usually trailing comma or unquoted key).
  2. Prefer writing values through `./bin/config set <key> <json>` which serializes valid JSON for you.
  3. Keep local.json in version control or backups so a broken edit can be reverted instantly.

Example fix

// before: conf/local/local.json with trailing comma
{
  "phabricator.base-uri": "https://phab.example.com",
}

// after: strict JSON
{
  "phabricator.base-uri": "https://phab.example.com"
}
Defensive patterns

Strategy: validation

Validate before calling

$path = PhabricatorEnv::getEnvConfig(...) ? null : 'conf/local/local.json';
$json = file_get_contents('conf/local/local.json');
if (json_decode($json) === null && json_last_error() !== JSON_ERROR_NONE) {
  throw new Exception('local.json: '.json_last_error_msg());
}

Prevention

When it happens

Trigger: Hand-editing conf/local/local.json and saving a syntax error - unquoted keys, a trailing comma after the last entry, single quotes, a stray semicolon, or a file truncated by an interrupted editor session; then any request or bin script that boots the env.

Common situations: Operators hand-editing local.json under time pressure instead of using ./bin/config set; merge conflict artifacts left in the file; editors inserting BOM or pretty-printing with wrong quoting; copying config snippets from wiki pages that include comments.

Related errors


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