phalcon/cphalcon · error · Phalcon\Db\Exceptions\SavepointsNotSupported
Savepoints are not supported by this database adapter
Error message
Savepoints are not supported by this database adapter
What it means
createSavepoint() first asks the adapter's dialect supportsSavePoints(); if the dialect reports no savepoint support, SavepointsNotSupported is thrown before any SQL is sent. All bundled dialects (Mysql, Postgresql, Sqlite) inherit the base Phalcon\Db\Dialect::supportsSavepoints() which returns true, so in practice this fires when a custom dialectClass overrides supportsSavePoints() to false or a hand-written DialectInterface implementation returns false/null.
Source
Thrown at phalcon/Db/Adapter/AbstractAdapter.zep:308
this->dialect->addPrimaryKey(
tableName,
schemaName,
index
)
);
}
/**
* Creates a new savepoint
*/
public function createSavepoint( string name) -> bool
{
var dialect;
let dialect = this->dialect;
if unlikely !dialect->supportsSavePoints() {
throw new SavepointsNotSupported();
}
return this->{"execute"}(
dialect->createSavepoint(name)
);
}
/**
* Creates a table
*/
public function createTable( string tableName, string schemaName, array definition) -> bool
{
var columns;
if unlikely !fetch columns, definition["columns"] {
throw new TableMustHaveColumn();
}
View on GitHub (pinned to b7419de9cd)
Solutions
- Check $connection->getDialect()->supportsSavePoints() before calling createSavepoint()
- If the database does support SAVEPOINT, fix the custom dialect: extend Phalcon\Db\Dialect (inherits true) or override supportsSavePoints() to return true
- Avoid nested transactions: do not call setNestedTransactionsWithSavepoints(true) and keep transaction level at 1
Example fix
// before
$connection->createSavepoint('LEVEL_1');
// after
if ($connection->getDialect()->supportsSavePoints()) {
$connection->createSavepoint('LEVEL_1');
} else {
// fall back to flat transactions: commit/rollback at level 1 only
} Defensive patterns
Strategy: validation
Validate before calling
if (!$connection->getDialect()->supportsSavePoints()) {
// run without savepoints: keep the transaction flat instead of creating one
return;
}
$connection->createSavepoint($name); Try / catch
use Phalcon\Db\Exceptions\SavepointsNotSupported;
try {
$connection->createSavepoint($name);
} catch (SavepointsNotSupported $e) {
// degrade gracefully: continue in a flat, non-nested transaction
$logger->warning('Savepoints unavailable, nesting disabled: ' . $e->getMessage());
} Prevention
- Query supportsSavePoints() once at startup and store the capability next to the adapter
- Make custom dialects extend Phalcon\Db\Dialect so support flags are accurate
- Design transaction helpers to degrade to flat transactions when the dialect lacks savepoints
When it happens
Trigger: Direct call $connection->createSavepoint('my_savepoint') while the configured dialect reports no savepoint support; or enabling nested transactions with savepoints ($connection->setNestedTransactionsWithSavepoints(true)) and then calling begin() repeatedly so the second nesting level issues createSavepoint().
Common situations: Custom dialect for a database/proxy layer that genuinely lacks SAVEPOINT; test doubles whose supportsSavePoints() returns false by default (PHPUnit mocks return null/false); a hand-implemented DialectInterface that forgot the support methods; adapters for platforms without nested-transaction support.
Related errors
- Nested transaction with savepoints behavior cannot be change
- The 'dialectClass' '{className}' must implement Phalcon\Db\D
- There is no active transaction
- The table must contain at least one column
- Unable to insert into {table} without data
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/11481ff913d8faf5.
Report an issue: GitHub.