Problem
Calling mysqli::rollback() or mysqli::begin_transaction() inside the
PHP-WASM sandbox runtime traps the interpreter with RuntimeError: unreachable.
The trap is unrecoverable — the recipe-run cannot continue, and the failure
surfaces as an unclaimed fatal before PHPUnit reports anything, so the
consumer sees "zero executed tests" rather than a diagnosable error.
Faulting stack
From logs/recipe-run.stderr.log in a managed-phpunit-evidence artifact:
Unhandled rejection: RuntimeError: unreachable
at php.wasm.zend_parse_method_parameters (wasm-function[314]:0x2905d)
at php.wasm.zif_mysqli_rollback (wasm-function[13621]:0x9d900a)
at php.wasm.ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER (wasm-function[22510]:0xddf366)
at php.wasm.execute_ex (wasm-function[18869]:0xc05944)
at php.wasm.zend_execute (wasm-function[5524]:0x40eab2)
at php.wasm.zend_execute_script (wasm-function[14587]:0xa56ed3)
at php.wasm.dynCall_iiii (wasm-function[19149]:0xc31bdb)
at Object.wrapper [as iiii] (runtime-overlays/php-wasm-node-8-4/asyncify/php_8_4.js:9965:13)
at invoke_iiii (runtime-overlays/php-wasm-node-8-4/asyncify/php_8_4.js:12333:27)
at php.wasm.php_execute_script_ex (wasm-function[8742]:0x69cf2b)
Recipe run interrupted by SIGTERM
The trap originates in zend_parse_method_parameters called from
zif_mysqli_rollback.
Observed on wp-codebox a7d8d7699f3d703b92fbd3e61bd124d13a7ad75d, runtime
overlay php-wasm-node-8-4, PHP 8.4, Node 24, Linux, with an external
MySQL 8.0 database service (WP_CODEBOX_DB_HOST=127.0.0.1:3306), i.e. a real
MySQL server rather than SQLite.
Reproduction shape
- Sandbox runtime,
database_type: mysql, external MySQL service.
- Open a second mysqli session alongside WordPress's own connection.
- Call
begin_transaction() or rollback() on it.
Both methods trap. Ordinary mysqli queries on the same connection work — it is
specifically the transaction API.
Evidence that it is narrowly the transaction methods
Across 15 PHPUnit suites in one run:
| Suite |
Runtime |
Result |
A (calls rollback()) |
sandbox |
zif_mysqli_rollback trap |
B (calls begin_transaction()) |
sandbox |
zif_mysqli_begin_transaction trap |
C (calls rollback()) |
sandbox |
zif_mysqli_rollback trap |
| D (sandbox, MySQL, no transaction calls) |
sandbox |
clean |
| E (managed WordPress, sandbox) |
sandbox |
clean |
| 10 further suites |
host |
clean |
Suite D is the important control: a sandbox MySQL suite that does not use
the transaction API runs clean. So the trigger is not "sandbox + MySQL", it is
the transaction methods specifically.
Impact
Any workload proving lock contention, isolation levels, or rollback semantics
between two connections cannot run in the sandbox runtime. In our case three
suites have been failing continuously since early September — the interpreter
dies before PHPUnit emits results, so CI reports zero executed tests with no
indication of which call was responsible. Recovering the actual cause required
downloading the evidence artifact and reading the WASM stack by hand.
Requests, in priority order
- Fail gracefully rather than trapping. Even a clear PHP-level fatal
("mysqli transactions are not supported in this runtime") would be a large
improvement over an unrecoverable WASM trap that destroys the run.
- Document the limitation so consumers can route affected suites to a host
runtime deliberately instead of discovering it from a stack trace.
- Support the transaction API if feasible in the WASM mysqli build.
Happy to test a fix or provide the full artifact.
Related
Problem
Calling
mysqli::rollback()ormysqli::begin_transaction()inside thePHP-WASM sandbox runtime traps the interpreter with
RuntimeError: unreachable.The trap is unrecoverable — the recipe-run cannot continue, and the failure
surfaces as an unclaimed fatal before PHPUnit reports anything, so the
consumer sees "zero executed tests" rather than a diagnosable error.
Faulting stack
From
logs/recipe-run.stderr.login amanaged-phpunit-evidenceartifact:The trap originates in
zend_parse_method_parameterscalled fromzif_mysqli_rollback.Observed on wp-codebox
a7d8d7699f3d703b92fbd3e61bd124d13a7ad75d, runtimeoverlay
php-wasm-node-8-4, PHP 8.4, Node 24, Linux, with an externalMySQL 8.0 database service (
WP_CODEBOX_DB_HOST=127.0.0.1:3306), i.e. a realMySQL server rather than SQLite.
Reproduction shape
database_type: mysql, external MySQL service.begin_transaction()orrollback()on it.Both methods trap. Ordinary mysqli queries on the same connection work — it is
specifically the transaction API.
Evidence that it is narrowly the transaction methods
Across 15 PHPUnit suites in one run:
rollback())zif_mysqli_rollbacktrapbegin_transaction())zif_mysqli_begin_transactiontraprollback())zif_mysqli_rollbacktrapSuite D is the important control: a sandbox MySQL suite that does not use
the transaction API runs clean. So the trigger is not "sandbox + MySQL", it is
the transaction methods specifically.
Impact
Any workload proving lock contention, isolation levels, or rollback semantics
between two connections cannot run in the sandbox runtime. In our case three
suites have been failing continuously since early September — the interpreter
dies before PHPUnit emits results, so CI reports zero executed tests with no
indication of which call was responsible. Recovering the actual cause required
downloading the evidence artifact and reading the WASM stack by hand.
Requests, in priority order
("mysqli transactions are not supported in this runtime") would be a large
improvement over an unrecoverable WASM trap that destroys the run.
runtime deliberately instead of discovering it from a stack trace.
Happy to test a fix or provide the full artifact.
Related
that issue's production evidence was misread on my side and has been
corrected there; the defect it fixes is genuine but was not this failure.