{"record":{"id":"cd667e0236dfc70a","repo":"passbolt/passbolt_api","slug":"cleanup-command-cannot-be-executed-on-an-instance-having-no-cd667e","errorCode":null,"errorMessage":"Cleanup command cannot be executed on an instance having no active administrator.","messagePattern":"Cleanup command cannot be executed on an instance having no active administrator\\.","errorType":"console","errorClass":"InternalErrorException","httpStatus":500,"severity":"error","filePath":"src/Command/CleanupCommand.php","lineNumber":229,"sourceCode":"     * @return void\n     * @throws \\Cake\\Http\\Exception\\InternalErrorException If database is not in valid state.\n     */\n    private function assertDatabaseState(): void\n    {\n        // Check 1. Users table exist in db\n        /** @var \\Cake\\Database\\Connection $connection */\n        $connection = ConnectionManager::get('default');\n        $listTables = $connection->getSchemaCollection()->listTables();\n        if (!in_array('users', $listTables)) {\n            throw new InternalErrorException(\n                __('Cleanup command cannot be executed on an instance having no users table.')\n            );\n        }\n\n        // Check 2. Atleast one active administrator is present\n        $admin = $this->Users->findFirstAdmin();\n        if (is_null($admin)) {\n            throw new InternalErrorException(\n                __('Cleanup command cannot be executed on an instance having no active administrator.')\n            );\n        }\n    }\n\n    /**\n     * Convert the method name to a human readeable string. eg. \"cleanupMethodName\" become \"Method Name\".\n     *\n     * @param string $methodName Method name\n     * @return string\n     */\n    private function methodNameToCleanupName(string $methodName): string\n    {\n        // Remove the \"cleanup\" prefix if present\n        $name = preg_replace('/^cleanup/i', '', $methodName);\n        if ($name === '' || $name === null) {\n            $name = $methodName;\n        }","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Command/CleanupCommand.php#L211-L247","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// SQL before (no active admin found)\nSELECT * FROM users WHERE is_active = false;\n-- after: reactivate the admin\nUPDATE users SET is_active = true WHERE id = '<admin-uuid>';\n$ bin/cake passbolt cleanup","handlingStrategy":"validation","validationCode":"$adminCount = TableRegistry::getTableLocator()->get('Users')->find()\n    ->innerJoinWith('Roles', fn($q) => $q->where(['Roles.name' => 'admin']))\n    ->where(['Users.is_active' => true, 'Users.is_deleted' => false])\n    ->count();\nif ($adminCount === 0) { die(\"Recover/create an active admin before running cleanup.\\n\"); }","typeGuard":null,"tryCatchPattern":"try {\n    $this->CleanupCommand->execute(...);\n} catch (InternalErrorException $e) {\n    if (str_contains($e->getMessage(), 'no active administrator')) {\n        // bootstrap an admin account first, then retry\n    }\n}","preventionTips":["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."],"tags":["cli","database","user-management","precondition-check"],"backgroundTag":"empty-result-set","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}