phalcon/cphalcon · error · Phalcon\Session\Exceptions\InvalidSessionAdapter

The session adapter is not valid

Error message

The session adapter is not valid

What it means

Manager::start() registers the handler with session_set_save_handler() before calling session_start(); it requires that an adapter implementing SessionHandlerInterface was set via setAdapter(). If no adapter was registered, or the object is not a session handler (e.g. a Phalcon Storage cache adapter), start() throws InvalidSessionAdapter.

Source

Thrown at phalcon/Session/Manager.zep:365

            return false;
        }

        /**
         * Verify that the session cookie value uses the PHP session ID
         * alphabet ([a-zA-Z0-9,-], depending on session.sid_bits_per_character),
         * otherwise we unset the cookie to allow it to be created by
         * session_start().
         */
        let name = this->getName();

        if fetch value, _COOKIE[name] {
            if !preg_match("/^[a-zA-Z0-9,-]+$/D", value) {
                unset _COOKIE[name];
            }
        }

        if unlikely !(this->adapter instanceof SessionHandlerInterface) {
            throw new InvalidSessionAdapter();
        }

        /**
         * Register the adapter
         */
        session_set_save_handler(this->adapter);

        /**
         * Start the session
         */
        return session_start();
    }

    /**
     * Returns the status of the current session.
     */
    public function status() -> int
    {

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Register a real session handler before start(): $session->setAdapter(new \Phalcon\Session\Adapter\Stream(['savePath' => ...])) or the Redis adapter
  2. When using the DI container, create the adapter inside the 'session' service closure so it can never be missing
  3. For custom handlers, implement \SessionHandlerInterface (open, close, read, write, destroy, gc, optionally validateId, updateTimestamp)
  4. Fail fast after wiring: if (!$session->getAdapter() instanceof \SessionHandlerInterface) { throw new ...; }

Example fix

// before
$session = new \Phalcon\Session\Manager();
$session->start(); // InvalidSessionAdapter

// after
$session = new \Phalcon\Session\Manager();
$session->setAdapter(new \Phalcon\Session\Adapter\Stream(['savePath' => '/tmp']));
$session->start();
Defensive patterns

Strategy: validation

Validate before calling

if (!$session->getAdapter() instanceof \SessionHandlerInterface) {
    $session->setAdapter(
        new \Phalcon\Session\Adapter\Stream(['savePath' => $config->path('session.savePath')])
    );
}

Type guard

function isSessionHandler(mixed $adapter): bool
{
    return $adapter instanceof \SessionHandlerInterface;
}

Try / catch

try {
    $session->start();
} catch (\Phalcon\Session\Exceptions\InvalidSessionAdapter $e) {
    $logger->critical('Session manager has no adapter; check DI service wiring');
    throw $e;
}

Prevention

When it happens

Trigger: Calling $session->start() on a Manager built with new Manager() and never calling setAdapter(); a DI 'session' service that returns the Manager without wiring the adapter; passing a Phalcon\Storage\Adapter\* object, which is a cache adapter, not a session handler.

Common situations: DI misconfiguration where the adapter line was dropped during refactor; code migrated from raw session_start(); developers confusing Storage adapters (cache) with Session adapters because both are named 'adapter'.

Related errors


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