symfony/process · error · LogicException

Start time is only available after process start.

Error message

Start time is only available after process start.

What it means

getStartTime() throws this LogicException when the process has never been started. The starttime property is only recorded in start(), so before any start the value is meaningless and the getter refuses to return it.

Solutions

  1. Guard with if ($process->isStarted()) before reading getStartTime().
  2. Track start time in caller code (microtime(true)) right before calling start().
  3. Call start() first, or throw/log a domain-level error when the process was expected to be running.

Example fix

// before
$elapsed = microtime(true) - $process->getStartTime(); // LogicException

// after
if ($process->isStarted()) {
    $elapsed = microtime(true) - $process->getStartTime();
}
Defensive patterns

Strategy: validation

Validate before calling

$startTime = $process->isStarted() ? $process->getStartTime() : null;

Try / catch

try {
    $startTime = $process->getStartTime();
} catch (\LogicException $e) {
    $startTime = null; // never started
}

Prevention

When it happens

Trigger: Calling getStartTime() on a freshly constructed Process that has not been started; also on a Process whose start failed before recording the time.

Common situations: Telemetry/logging code measuring elapsed time that reads getStartTime() unconditionally; components receiving a Process object without knowing whether start() was called.

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.

Related errors


AI-assisted analysis of symfony/process@99b85026db (2026-09-14). Data as JSON: /api/errors/d381d40c831f086e. Report an issue: GitHub.

Appendix: source

Thrown at Process.php:1238

            $this->stop(0);

            throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
        }

        if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) {
            $this->stop(0);

            throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
        }
    }

    /**
     * @throws LogicException in case process is not started
     */
    public function getStartTime(): float
    {
        if (!$this->isStarted()) {
            throw new LogicException('Start time is only available after process start.');
        }

        return $this->starttime;
    }

    /**
     * Defines options to pass to the underlying proc_open().
     *
     * @see https://php.net/proc_open for the options supported by PHP.
     *
     * Enabling the "create_new_console" option allows a subprocess to continue
     * to run after the main process exited, on both Windows and *nix
     */
    public function setOptions(array $options): void
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Setting options while the process is running is not possible.');
        }

View on GitHub (pinned to 99b85026db)