passbolt/passbolt_api · error · InternalErrorException
Cleanup command cannot be executed on an instance having no…
Error message
Cleanup command cannot be executed on an instance having no active administrator.
What it means
The cleanup command (bin/cake passbolt cleanup) repairs referential integrity of the database (deleted users, missing keys, permissions). Before running it asserts the database state, and Check 2 requires at least one active administrator (UsersTable::findFirstAdmin() returns null). Passbolt throws InternalErrorException because performing cleanup on an instance with no active admin would leave the instance administratively unrecoverable.
Solutions
- Re-activate an administrator directly in the database: UPDATE users SET is_active = 1, is_deleted = 0 WHERE id = (SELECT id FROM users u JOIN roles r ON r.id = u.role_id WHERE r.name = 'admin' LIMIT 1);
- If no admin account exists at all, register one with 'bin/cake passbolt register_user -r admin -u you@example.com -f First -l Last' after ensuring the roles table contains 'admin'.
- Restore the deleted admin account via 'bin/cake passbolt restore_deleted_user <userId>' if it was soft-deleted.
- Re-run 'bin/cake passbolt cleanup' once an active admin exists.
Example fix
// SQL before (no active admin found) SELECT * FROM users WHERE is_active = false; -- after: reactivate the admin UPDATE users SET is_active = true WHERE id = '<admin-uuid>'; $ bin/cake passbolt cleanup
Defensive patterns
Strategy: validation
Validate before calling
$adminCount = TableRegistry::getTableLocator()->get('Users')->find()
->innerJoinWith('Roles', fn($q) => $q->where(['Roles.name' => 'admin']))
->where(['Users.is_active' => true, 'Users.is_deleted' => false])
->count();
if ($adminCount === 0) { die("Recover/create an active admin before running cleanup.\n"); } Try / catch
try {
$this->CleanupCommand->execute(...);
} catch (InternalErrorException $e) {
if (str_contains($e->getMessage(), 'no active administrator')) {
// bootstrap an admin account first, then retry
}
} Prevention
- Never deactivate/delete the last admin without creating a replacement first.
- Monitor admin count in health/alerting scripts.
- After DB restores, verify an active admin exists before running cleanup.
When it happens
Trigger: Running 'bin/cake passbolt cleanup' when the users table has no user with role 'admin' and is_active=true (or is_deleted=false), so findFirstAdmin() returns null.
Common situations: All admins were soft-deleted or deactivated (e.g. offboarding every admin via UI/API); a data restore or migration dropped admin rows; the cleanup was run on a fresh/broken database before any admin user exists.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- Cleanup command cannot be executed on an instance having no…
- Data for cannot be imported
- No active admins were found.
- The user with username
- group(s) returned by your directory are invalid and will be…
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/cd667e0236dfc70a.
Report an issue: GitHub.
Appendix: source
Thrown at src/Command/CleanupCommand.php:229
* @return void
* @throws \Cake\Http\Exception\InternalErrorException If database is not in valid state.
*/
private function assertDatabaseState(): void
{
// Check 1. Users table exist in db
/** @var \Cake\Database\Connection $connection */
$connection = ConnectionManager::get('default');
$listTables = $connection->getSchemaCollection()->listTables();
if (!in_array('users', $listTables)) {
throw new InternalErrorException(
__('Cleanup command cannot be executed on an instance having no users table.')
);
}
// Check 2. Atleast one active administrator is present
$admin = $this->Users->findFirstAdmin();
if (is_null($admin)) {
throw new InternalErrorException(
__('Cleanup command cannot be executed on an instance having no active administrator.')
);
}
}
/**
* Convert the method name to a human readeable string. eg. "cleanupMethodName" become "Method Name".
*
* @param string $methodName Method name
* @return string
*/
private function methodNameToCleanupName(string $methodName): string
{
// Remove the "cleanup" prefix if present
$name = preg_replace('/^cleanup/i', '', $methodName);
if ($name === '' || $name === null) {
$name = $methodName;
}View on GitHub (pinned to 31c1bbc10f)