Summary
terminus remote:drush <site.env> -- sql-dump silently truncates output for large databases (~886 MB). The dump ends mid-INSERT with no -- Dump completed marker and exit code 0. Small databases (~1.5 MB) work fine.
This is a regression introduced in Terminus v4 via the upgrade to symfony/console 6.x.
Root Cause
SSHBaseCommand::getOutputCallback() writes SSH output through $output->write($buffer) using the default OUTPUT_NORMAL mode. This routes every chunk of SQL data through OutputFormatter::format(), which regex-parses the data looking for console-style tags (<info>, <error>, etc.).
Symfony Console 6.x introduced a ~27× performance regression in OutputFormatter::formatAndWrap() (see upstream issue). The slowdown creates backpressure through the SSH pipe, throttling the remote drush sql-dump process until it's killed by server-side execution limits—resulting in a silently truncated dump.
Two Issues
1. Performance regression (v4 only)
The symfony/console 6.x formatter is ~27× slower on HTML-rich text. For an 886 MB dump:
|
Terminus v3 (Console 5.4) |
Terminus v4 (Console 6.4) |
| Formatter time per chunk |
7.8ms |
212ms |
| Projected total |
~3.6 min |
~99 min |
| Dump result |
✅ Complete (886 MB) |
❌ Truncated (~848 KB) |
2. Latent data corruption (v3 and v4)
Both versions silently strip Symfony Console style tags from piped output. If any database content contains literal <info>, <error>, <comment>, <question>, or <fg=...> strings, they are removed from the dump:
Input: INSERT INTO node__body VALUES ('<info>Important notice</info>');
Output: INSERT INTO node__body VALUES ('Important notice');
This is rare in practice but means dumps are not byte-accurate even when they complete.
Suggested Fix
In src/Commands/Remote/SSHBaseCommand.php, the getOutputCallback() method should use OUTPUT_RAW:
private function getOutputCallback()
{
$output = $this->output();
$stderr = $this->stderr();
return function ($type, $buffer) use ($output, $stderr) {
if (Process::ERR === $type) {
$stderr->write($buffer);
} else {
$output->write($buffer, false, OutputInterface::OUTPUT_RAW);
}
};
}
OUTPUT_RAW bypasses OutputFormatter::format() entirely, which is correct for streaming raw command output. The formatter is designed for styled console messages, not for piping data.
This fixes both issues: the performance regression (no formatting overhead) and the data corruption (no tag stripping).
Reproduction
# Large database (fails with v4)
terminus remote:drush <site.env> -- sql-dump --structure-tables-list=cache,cache_* | wc -c
# Compare: same command via Terminus v3 produces ~886MB, v4 produces ~848KB
Environment
- Terminus v4.1.4 (symfony/console v6.4.32)
- Terminus v3.6.1 (symfony/console v5.4.43) — works correctly
- PHP 8.x
Disclaimer: Bug report heavily written by AI...
Summary
terminus remote:drush <site.env> -- sql-dumpsilently truncates output for large databases (~886 MB). The dump ends mid-INSERT with no-- Dump completedmarker and exit code 0. Small databases (~1.5 MB) work fine.This is a regression introduced in Terminus v4 via the upgrade to
symfony/console6.x.Root Cause
SSHBaseCommand::getOutputCallback()writes SSH output through$output->write($buffer)using the defaultOUTPUT_NORMALmode. This routes every chunk of SQL data throughOutputFormatter::format(), which regex-parses the data looking for console-style tags (<info>,<error>, etc.).Symfony Console 6.x introduced a ~27× performance regression in
OutputFormatter::formatAndWrap()(see upstream issue). The slowdown creates backpressure through the SSH pipe, throttling the remotedrush sql-dumpprocess until it's killed by server-side execution limits—resulting in a silently truncated dump.Two Issues
1. Performance regression (v4 only)
The
symfony/console6.x formatter is ~27× slower on HTML-rich text. For an 886 MB dump:2. Latent data corruption (v3 and v4)
Both versions silently strip Symfony Console style tags from piped output. If any database content contains literal
<info>,<error>,<comment>,<question>, or<fg=...>strings, they are removed from the dump:This is rare in practice but means dumps are not byte-accurate even when they complete.
Suggested Fix
In
src/Commands/Remote/SSHBaseCommand.php, thegetOutputCallback()method should useOUTPUT_RAW:OUTPUT_RAWbypassesOutputFormatter::format()entirely, which is correct for streaming raw command output. The formatter is designed for styled console messages, not for piping data.This fixes both issues: the performance regression (no formatting overhead) and the data corruption (no tag stripping).
Reproduction
Environment
Disclaimer: Bug report heavily written by AI...