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
- Register a real session handler before start(): $session->setAdapter(new \Phalcon\Session\Adapter\Stream(['savePath' => ...])) or the Redis adapter
- When using the DI container, create the adapter inside the 'session' service closure so it can never be missing
- For custom handlers, implement \SessionHandlerInterface (open, close, read, write, destroy, gc, optionally validateId, updateTimestamp)
- 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
- Construct Manager and adapter together in one factory/DI closure
- Never reuse a Phalcon\Storage cache adapter as a session handler
- Add a startup assertion on getAdapter() instanceof SessionHandlerInterface in test suites
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
- The session save path cannot be empty
- Configuration file {fileName} cannot be loaded
- The 'dialectClass' '{className}' must implement Phalcon\Db\D
- Nested transaction with savepoints behavior cannot be change
- Argument at position {} must have a type
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/4ff5d49c6e7edfcc.
Report an issue: GitHub.