coollabsio/coolify · error · Exception

Invalid Cron / Human expression

Error message

Invalid Cron / Human expression

What it means

The BackupEdit Livewire component validates backup->frequency with validate_cron_expression() before saving. That helper accepts a 5-field cron expression that dragonmantank/cron's CronExpression::isValid() approves, or one of Coolify's built-in human presets (keys of VALID_CRON_STRINGS). Anything else — empty value, typo'd preset, or malformed cron — throws this generic Exception from the component's update flow.

Source

Thrown at app/Livewire/Project/Database/BackupEdit.php:341

        // S3 backup cannot be enabled without a valid S3 storage owned by the team
        $availableS3Ids = $this->availableS3StorageIds();
        if ($availableS3Ids->isEmpty()) {
            $this->backup->s3_storage_id = $this->s3StorageId = null;
            if ($this->backup->save_s3) {
                $this->backup->save_s3 = $this->saveS3 = false;
            }
        } elseif (! $availableS3Ids->contains($this->backup->s3_storage_id)) {
            $this->backup->s3_storage_id = $this->s3StorageId = $availableS3Ids->first();
        }

        // Validate that disable_local_backup can only be true when S3 backup is enabled
        if ($this->backup->disable_local_backup && ! $this->backup->save_s3) {
            $this->backup->disable_local_backup = $this->disableLocalBackup = false;
        }

        $isValid = validate_cron_expression($this->backup->frequency);
        if (! $isValid) {
            throw new Exception('Invalid Cron / Human expression');
        }
        $this->validate();
    }

    private function availableS3StorageIds(): Collection
    {
        $storages = collect($this->availableS3Storages);
        $storageIds = $storages->pluck('id')->filter()->all();

        if (empty($storageIds)) {
            return collect();
        }

        $teamIds = $storages->pluck('team_id')->reject(fn ($teamId) => $teamId === null)->unique()->values()->all();

        if (empty($teamIds)) {
            return collect();
        }

View on GitHub (pinned to 70b9acc424)

Solutions

  1. Set frequency to a standard 5-field cron expression, e.g. '0 2 * * *' for 02:00 daily.
  2. Or pick one of Coolify's presets from the dropdown (keys of VALID_CRON_STRINGS in bootstrap/helpers, e.g. every_minute / every_hour).
  3. Trim accidental whitespace and make sure the field is not empty before submitting.
  4. If an existing backup suddenly fails after an upgrade, re-select its schedule from the UI dropdown and save again.

Example fix

// before
$backup->frequency = '@fortnightly';

// after: plain 5-field cron, Mondays 03:00
$backup->frequency = '0 3 * * 1';
Defensive patterns

Strategy: validation

Validate before calling

// Validate before persisting any backup frequency
if (! validate_cron_expression(trim($frequency))) {
    return back()->withErrors(['frequency' => 'Invalid cron or preset expression']);
}

Try / catch

In Livewire: try { $this->validateFrequency(); } catch (Exception $e) { $this->addError('backup.frequency', 'Use a 5-field cron expression or a preset from the dropdown.'); }

Prevention

When it happens

Trigger: Saving a scheduled database backup with a frequency that is neither valid 5-field cron nor a supported preset string; the field left empty by a form reset; pasting a 6-field (with seconds) or 7-field cron from another system; stray whitespace/newlines in the input.

Common situations: Typing free text instead of picking the UI dropdown preset; using '@fortnightly' or other expressions the cron library rejects; old backup rows whose frequency a cron-library upgrade now refuses to validate.

Related errors


AI-assisted analysis of coollabsio/coolify@70b9acc424 (2026-08-17). Data as JSON: /api/errors/5458273e9de70870. Report an issue: GitHub.