phalcon/cphalcon · error · Phalcon\Session\Adapter\Exceptions\InvalidSavePath

The session save path cannot be empty

Error message

The session save path cannot be empty

What it means

Phalcon\Session\Adapter\Stream (the file-based session handler) resolves its storage directory in the constructor: it takes options['savePath'] and falls back to the session.save_path php.ini directive. InvalidSavePath is thrown when both resolve to an empty value, so the adapter has no directory in which to create session files.

Solutions

  1. Pass an explicit savePath option: new Stream(['savePath' => '/tmp/phalcon-sessions'])
  2. Set session.save_path in php.ini (e.g. session.save_path = '/var/lib/php/sessions') and restart PHP-FPM
  3. If php.ini is not editable, call ini_set('session.save_path', $dir) before constructing the adapter
  4. Add a bootstrap assertion on ini_get('session.save_path') so misconfigured environments fail at deploy, not at first request

Example fix

// before
$session->setAdapter(new Stream()); // InvalidSavePath when session.save_path is empty

// after
$session->setAdapter(new Stream(['savePath' => '/tmp/phalcon-sessions']));
Defensive patterns

Strategy: validation

Validate before calling

$savePath = $options['savePath'] ?? ini_get('session.save_path');
if ($savePath === false || $savePath === '') {
    throw new RuntimeException(
        'No session save path: pass Stream option \'savePath\' or set session.save_path'
    );
}

Prevention

When it happens

Trigger: new Stream() or new Stream(['prefix' => 'x']) with no 'savePath' option while php.ini/CLI has no session.save_path set; PHP-FPM pools commonly ship with session.save_path empty, as do CLI scripts, containers and fresh minimal PHP installs.

Common situations: Fresh Docker/CLI/FPM environments where session.save_path was never configured; deploying to a new server after the adapter worked locally; a php.ini that sets session.save_path but the pool overrides it with an empty value.

Related errors


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

Appendix: source

Thrown at phalcon/Session/Adapter/Stream.zep:94

     *
     * @throws InvalidSavePath
     * @throws SavePathUnavailable
     */
    public function __construct( array options = [])
    {
        var path;

        let this->prefix  = this->getArrVal(options, "prefix", ""),
            this->options = options;

        /**
         * Get the save_path from the passed options. If not defined
         * get it from php.ini
         */
        let path = this->getArrVal(options, "savePath", this->phpIniGet("session.save_path"));

        if unlikely true === empty(path) {
            throw new InvalidSavePath();
        }

        if unlikely true !== this->phpIsWritable(path) {
            throw new SavePathUnavailable(path);
        }

        let this->path = this->toDirSeparator(path);
    }

    public function destroy(string id) -> bool
    {
        var file;

        let file = this->path . this->getPrefixedName(id);

        if this->phpFileExists(file) && is_file(file) {
            this->phpUnlink(file);
        }

View on GitHub (pinned to b7419de9cd)