flarum/framework · error · StepFailed
Step failed
Error message
Step failed
What it means
Generic wrapper exception (StepFailed) thrown by the install Pipeline when any pipeline step throws. The original error is preserved as the previous exception, while 'Step failed' identifies which phase of installation aborted; reversible steps already run are rolled back.
Solutions
- Inspect the previous exception: catch StepFailed and log/getPrevious()->getMessage() for the root cause.
- Fix the underlying error reported by the wrapped exception (permissions, DB, disk).
- Re-run the installer after fixing; already-completed reversible steps are rolled back so it is safe.
- Enable verbose logging via pipeline 'fail' callbacks to capture the failing step name.
Example fix
// before
try {
$pipeline->run();
} catch (Exception $e) {
echo $e->getMessage(); // 'Step failed' — useless
}
// after
try {
$pipeline->run();
} catch (StepFailed $e) {
$step = ...; // track via 'fail' callback
$cause = $e->getPrevious();
echo "Install step {$step} failed: ".$cause?->getMessage();
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight checks before running the pipeline:
is_writable($configDir) || throw new RuntimeException("{$configDir} is not writable");
(new PDO("mysql:host={$host};dbname={$db}", $user, $pass)); // verify DB reachable Type guard
null
Try / catch
try {
$pipeline->run();
} catch (StepFailed $e) {
$logger->error('Install failed', [
'step' => $e->getPrevious()?->getMessage(),
'previous' => $e->getPrevious(),
]);
} Prevention
- Register a 'fail' callback on the pipeline to log the failing step.
- Pre-check DB connectivity and directory permissions before running the installer.
- Always unwrap getPrevious() — 'Step failed' is never the root cause.
When it happens
Trigger: Any Install step (writing config, connecting to DB, running migrations, creating admin user, publishing assets) throwing an Exception during Pipeline::run.
Common situations: DB connection failure mid-install; unwritable config directory; migration SQL errors; file permission issues during asset publishing. The real cause is in the wrapped exception.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
AI-assisted analysis of flarum/framework@4b939f6853 (2026-09-15).
Data as JSON: /api/errors/7911ca9428259cde.
Report an issue: GitHub.
Appendix: source
Thrown at framework/core/src/Install/Pipeline.php:76
/**
* @param callable(): Step $factory
* @throws StepFailed
*/
private function runStep(callable $factory): void
{
$step = $factory();
$this->fireCallbacks('start', $step);
try {
$step->run();
$this->successfulSteps->push($step);
$this->fireCallbacks('end', $step);
} catch (Exception $e) {
$this->fireCallbacks('fail', $step);
throw new StepFailed('Step failed', 0, $e);
}
}
private function revertReversibleSteps(): void
{
foreach ($this->successfulSteps as $step) {
if ($step instanceof ReversibleStep) {
$this->fireCallbacks('rollback', $step);
$step->revert();
}
}
}
private function fireCallbacks(string $event, Step $step): void
{
if (isset($this->callbacks[$event])) {
($this->callbacks[$event])($step);View on GitHub (pinned to 4b939f6853)