flarum/framework · error · InvalidArgumentException

Last update runs can only be for one of: minor, major…

Error message

Last update runs can only be for one of: minor, major, global

What it means

LastUpdateRun::for() restricts its argument to the three FlarumUpdated constants: MAJOR, MINOR and GLOBAL. Any other string is rejected with an InvalidArgumentException before being stored as the active update type. This prevents recording update-run state for unknown update categories.

Solutions

  1. Pass one of FlarumUpdated::MAJOR, FlarumUpdated::MINOR or FlarumUpdated::GLOBAL instead of a raw string.
  2. Validate/normalize the incoming update kind (strtolower + whitelist check) before calling for().
  3. If you need a new update category, extend the allowed list in FlarumUpdated and in this check rather than passing an ad-hoc string.

Example fix

// before
$lastUpdateRun->for($input['update_type']);
// after
$kind = strtolower(trim($input['update_type']));
if (! in_array($kind, [FlarumUpdated::MAJOR, FlarumUpdated::MINOR, FlarumUpdated::GLOBAL], true)) {
    throw new \InvalidArgumentException('Unsupported update type');
}
$lastUpdateRun->for($kind);
Defensive patterns

Strategy: validation

Validate before calling

$allowed = [FlarumUpdated::MAJOR, FlarumUpdated::MINOR, FlarumUpdated::GLOBAL];
if (! in_array($update, $allowed, true)) {
    throw new \InvalidArgumentException('Update type must be one of: ' . implode(', ', $allowed));
}

Type guard

function isValidUpdateType(string $v): bool {
    return in_array($v, [FlarumUpdated::MAJOR, FlarumUpdated::MINOR, FlarumUpdated::GLOBAL], true);
}

Try / catch

try {
    $lastUpdateRun->for($update);
} catch (\InvalidArgumentException $e) {
    // normalize or log invalid update type
    $update = strtolower($update);
}

Prevention

When it happens

Trigger: Calling LastUpdateRun::for() with a literal string such as 'patch', 'security', 'Major' (wrong case), or a translated/custom label instead of exactly FlarumUpdated::MAJOR ('major'), ::MINOR ('minor') or ::GLOBAL ('global').

Common situations: Hard-coding the update kind in extension code instead of importing the FlarumUpdated constants; case mismatch when the value comes from user input or a config file; passing an update type added in a newer Flarum version that this Settings class doesn't whitelist.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of flarum/framework@4b939f6853 (2026-09-15). Data as JSON: /api/errors/4950f5e18d199b6e. Report an issue: GitHub.

Appendix: source

Thrown at extensions/package-manager/src/Settings/LastUpdateRun.php:32

use Flarum\Settings\SettingsRepositoryInterface;

class LastUpdateRun implements JsonSetting
{
    public const SUCCESS = 'success';
    public const FAILURE = 'failure';
    protected array $data;
    protected ?string $activeUpdate;

    public function __construct(
        protected SettingsRepositoryInterface $settings,
    ) {
        $this->data = self::default();
    }

    public function for(string $update): self
    {
        if (! in_array($update, [FlarumUpdated::MAJOR, FlarumUpdated::MINOR, FlarumUpdated::GLOBAL])) {
            throw new \InvalidArgumentException('Last update runs can only be for one of: minor, major, global');
        }

        $this->activeUpdate = $update;

        return $this;
    }

    public function with(string $key, mixed $value): JsonSetting
    {
        $this->data[$this->activeUpdate][$key] = $value;

        return $this;
    }

    public function save(): array
    {
        $this->data[$this->activeUpdate]['ranAt'] = Carbon::now();

View on GitHub (pinned to 4b939f6853)