getgrav/grav · error · RuntimeException
No backups defined...
Error message
No backups defined...
What it means
Backups::backup($id) loads the backup profile list from the configuration key backups.profiles (user/config/backups.yaml merged over system/config/backups.yaml) and indexes it by integer. If $id is not a key in that list — because the list is missing, null, or simply shorter than the id — it throws RuntimeException 'No backups defined...'. It is a configuration lookup failure, not a filesystem one.
Source
Thrown at system/src/Grav/Common/Backup/Backups.php:238
*/
public static function backup($id = 0, ?callable $status = null, ?string $environment = null)
{
$grav = Grav::instance();
// If environment is specified and different from current, reload config
if ($environment && $environment !== $grav['config']->get('setup.environment')) {
$grav->setup($environment);
$grav['config']->reload();
}
$profiles = static::getBackupProfiles();
/** @var UniformResourceLocator $locator */
$locator = $grav['locator'];
if (isset($profiles[$id])) {
$backup = (object) $profiles[$id];
} else {
throw new RuntimeException('No backups defined...');
}
$name = $grav['inflector']->underscorize($backup->name);
$date = date(static::BACKUP_DATE_FORMAT, time());
$filename = trim((string) $name, '_') . '--' . $date . '.zip';
$grav['backups']->setup();
$destination = static::$backup_dir . DS . $filename;
$max_execution_time = ini_set('max_execution_time', '600');
$backup_root = $backup->root;
if ($locator->isStream($backup_root)) {
$backup_root = $locator->findResource($backup_root);
} else {
$backup_root = rtrim(GRAV_ROOT . $backup_root, DS) ?: DS;
}
if (!$backup_root || !file_exists($backup_root)) {
throw new RuntimeException("Backup location: {$backup_root} does not exist...");View on GitHub (pinned to 6040efed04)
Solutions
- Inspect Backups::getBackupProfiles() (i.e. config backups.profiles) and confirm the id you pass is a valid array key
- Restore or fix user/config/backups.yaml so profiles is a non-empty list with name/root/schedule fields
- Re-register scheduler jobs after changing profiles (the job list is rebuilt from the current config on each scheduler run)
- When calling backup($id, $status, $environment), verify the profile exists in that environment's config, not just the default one
Example fix
// before
Backups::backup($id); // throws when $id is stale
// after
$profiles = Backups::getBackupProfiles();
if (!is_array($profiles) || !isset($profiles[$id])) {
throw new RuntimeException(sprintf('Backup profile %d not found in backups.profiles', $id));
}
Backups::backup($id); Defensive patterns
Strategy: validation
Validate before calling
$profiles = Backups::getBackupProfiles();
if (!is_array($profiles) || !isset($profiles[$id])) {
// log and bail out with a clear message instead of letting backup() throw
return;
} Try / catch
try {
Backups::backup($id);
} catch (RuntimeException $e) {
// covers 'No backups defined...', missing roots, and containment rejects
$log->error('Backup failed: ' . $e->getMessage());
} Prevention
- After editing backups.profiles, re-check scheduler registrations — jobs capture the profile id when built
- Treat profile ids as unstable: key custom logic on profile name, not array index
- When using the $environment argument, verify the profile exists under that environment's merged config
When it happens
Trigger: Calling Backups::backup(2) when only two profiles exist (valid ids 0 and 1); running a scheduled job that was registered from an older profile list whose ids no longer exist (onSchedulerInitialized captures $id at schedule time); user/config/backups.yaml overriding profiles with an empty value; invoking the admin Backups tool task with a stale id after profiles were edited.
Common situations: Profiles were renamed/reordered so array keys shifted; backups.yaml was emptied or corrupted during a migration; a cron/scheduler job survived a config change that removed its profile; environment mismatch — backup() was called with an $environment whose config reload produced a different profile set.
Related errors
- Backup location: {$backup_root} does not exist...
- Invalid backup location: {$backup_root}
- Backup location not allowed (outside site root): {$backup_ro
- Cache folder not defined.
- Setup: Configuration reload loop detected!
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/fa9bab311a94c9af.
Report an issue: GitHub.