phalcon/cphalcon · error · Phalcon\Auth\Exceptions\FileCannotRead

Stream adapter cannot read file: {path}

Error message

Stream adapter cannot read file: {path}

What it means

After confirming the users file exists, the Auth Stream adapter reads it with file_get_contents; a false return (not mere emptiness) means the OS refused the read, and the adapter reports FileCannotRead with the path. This is an environment/permission problem, not a content problem — JSON validity is checked later.

Source

Thrown at phalcon/Auth/Adapter/Stream.zep:79

     *
     * @phpstan-return list<AuthUserRow>
     *
     * @throws Exception
     */
    protected function loadUsers() -> array
    {
        var contents, data, ex, path, rows;

        let path = this->config->getFile();

        if (!this->phpFileExists(path)) {
            throw new FileDoesNotExist(path);
        }

        let contents = this->phpFileGetContents(path);

        if (contents === false) {
            throw new FileCannotRead(path);
        }

        try {
            let data = (new Decode())->__invoke(contents, true);
        } catch InvalidArgumentException, ex {
            throw new FileNotValidJson(path, ex);
        }

        if (typeof data !== "array") {
            throw new FileDoesNotContainJson(path);
        }

        /** @var list<AuthUserRow> $rows */
        let rows = array_values(data);

        return rows;
    }
}

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Grant read access: `chown www-data:www-data storage/users.json` or `chmod 640` with proper group
  2. Verify with `sudo -u www-data cat <path>` to reproduce the exact denial
  3. Check open_basedir/SELinux (`getenforce`, audit log) and allow the directory

Example fix

# before: file owned by root, php-fpm runs as www-data
-rw------- 1 root root storage/users.json
# after
chown www-data:www-data storage/users.json
chmod 640 storage/users.json
Defensive patterns

Strategy: validation

Validate before calling

$file = $config->getFile();
if (!is_readable($file)) {
    throw new RuntimeException('Auth users file not readable by this process: ' . $file);
}
$adapter = new \Phalcon\Auth\Adapter\Stream($hasher, $config);

Try / catch

try {
    $guard->attempt($credentials);
} catch (\Phalcon\Auth\Exceptions\FileCannotRead $e) {
    $logger->critical('Permissions problem on auth users file: ' . $e->getMessage());
    throw new RuntimeException('Authentication store unavailable', 0, $e);
}

Prevention

When it happens

Trigger: Authenticating via the Stream adapter where the file exists but is unreadable by the PHP process: wrong owner/mode, open_basedir excluding the directory, SELinux denial, or a dangling symlink.

Common situations: Files created by root/deploy user while php-fpm runs as www-data; hardened shared hosting with open_basedir; container images with restrictive umasks; symlink to a protected location.

Related errors


AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21). Data as JSON: /api/errors/c15d41563b05faf0. Report an issue: GitHub.