TryGhost/Ghost · error · Error
Command failed with exit code ${exitCode}: ${command}\nSTDOU
Error message
Command failed with exit code ${exitCode}: ${command}\nSTDOUT: ${stdout}\nSTDERR: ${stderr} What it means
MysqlManager runs a command inside the MySQL container via Docker exec, collects stdout/stderr streams, then inspects the exec for ExitCode. Any non-zero exit code produces this error embedding the command, stdout, and stderr. It's a thin wrapper surfacing the real failure of mysql/mysqladmin/sql inside the container (auth, syntax, missing DB, locked table).
Source
Thrown at e2e/helpers/environment/service-managers/mysql-manager.ts:256
// Use Docker modem's demuxStream to separate stdout and stderr
(container as ContainerWithModem).modem.demuxStream(stream, stdoutStream, stderrStream);
// Wait for the stream to end
await new Promise<void>((resolve, reject) => {
stream.on('end', () => resolve());
stream.on('error', reject);
});
// Get the exit code from exec inspection
const execInfo = await exec.inspect();
const exitCode = execInfo.ExitCode;
const stdout = Buffer.concat(stdoutChunks).toString('utf8').trim();
const stderr = Buffer.concat(stderrChunks).toString('utf8').trim();
if (exitCode !== 0) {
throw new Error(
`Command failed with exit code ${exitCode}: ${command}\n` +
`STDOUT: ${stdout}\n` +
`STDERR: ${stderr}`
);
}
return stdout;
}
}
View on GitHub (pinned to 47d8b0e2ad)
Solutions
- Read STDERR in the message — the MySQL server error (access denied, unknown database, syntax) names the cause.
- Verify the credentials passed to exec match the container's MYSQL_ROOT_PASSWORD / user grants.
- Confirm the target database exists before running the command; create it if missing.
- Quote identifiers and validate SQL syntax before exec.
Example fix
// before: opaque exit-code failure
// after: validate DB exists and credentials before exec
const dbs = await mysqlManager.exec('mysql -uroot -p$PW -e "SHOW DATABASES"');
if (!dbs.includes(targetDb)) {
await mysqlManager.exec(`mysql -uroot -p$PW -e "CREATE DATABASE \`${targetDb}\""`);
} Defensive patterns
Strategy: try-catch
Validate before calling
async function dbExists(m: MysqlManager, name: string): Promise<boolean> {
const out = await m.exec(`mysql -uroot -p${PW} -e "SHOW DATABASES"`);
return out.split('\n').some(l => l === name);
} Try / catch
try {
return await mysqlManager.exec(command);
} catch (e) {
// message already embeds command/stdout/stderr — rethrow with cause for upstream context
throw new Error(`mysql exec failed: ${(e as Error).message}`, {cause: e});
} Prevention
- Validate the target DB exists and credentials are correct before running commands.
- Quote SQL identifiers and parameterize values to avoid syntax errors.
- Keep the manager's root password env in sync with the container's MYSQL_ROOT_PASSWORD.
When it happens
Trigger: Running mysql -e with wrong credentials (MYSQL_ROOT_PASSWORD mismatch). Querying a database that doesn't exist. SQL syntax error in the command. Container busy / table locked. The exec targeted a DB user lacking privileges.
Common situations: Wrong root password env between manager and container; database name typo; reserved keyword unquoted; flapping container where exec runs mid-restart.
Related errors
- Cannot insert without an id field
- ${entityType} with id ${id} not found
- Egress monitor sidecar did not start in time
- Egress monitor container has no network IP
- Build image not found: ${BUILD_IMAGE}\n\nYou are running in
AI-assisted analysis of TryGhost/Ghost@47d8b0e2ad (2026-08-13).
Data as JSON: /api/errors/d5421dc8e8aec1e2.
Report an issue: GitHub.