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
- Pass one of FlarumUpdated::MAJOR, FlarumUpdated::MINOR or FlarumUpdated::GLOBAL instead of a raw string.
- Validate/normalize the incoming update kind (strtolower + whitelist check) before calling for().
- 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
- Always use the FlarumUpdated class constants, never string literals.
- Normalize user/config-provided values with strtolower before passing.
- Whitelist-validate external input mapping to update kinds.
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
- Invalid erasure mode: $mode
- flarum/*
- Relation aggregates can only be used with number attributes
- Cannot modify immutable default setting $key.
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)