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

  1. Inspect the previous exception: catch StepFailed and log/getPrevious()->getMessage() for the root cause.
  2. Fix the underlying error reported by the wrapped exception (permissions, DB, disk).
  3. Re-run the installer after fixing; already-completed reversible steps are rolled back so it is safe.
  4. 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

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)