obaidullahrion Summary When users are deleted from the admin panel without first removing their backup schedules, orphaned BackupList records cause the backup cron job to crash with NoneType errors, resulting in only partial user backups. Description The backup system processes records from the BackupList database table. When a user is deleted from Django's auth_user table, their BackupList records become orphaned (pointing to non-existent user IDs). The backup cron job (manage.py backup --day/week/month/hour) processes these orphaned records and crashes, preventing remaining users from being backed up. Steps to Reproduce Create a user account Set up a backup schedule for that user (via admin panel) Delete the user from admin panel without first deleting their backup schedule Run the backup cron: manage.py backup --day Observe the crash --- Expected Behavior All valid users should be backed up successfully Deleted users' backup records should either: Be automatically deleted when user is deleted, OR Be safely skipped with a warning message --- Actual Behavior The backup cron crashes with the following error: Processing backups for day schedule... Error processing backup for 5: 'NoneType' object has no attribute 'get' Error processing backup for 6: 'NoneType' object has no attribute 'get' Impact: Only some users get backed up (e.g., "sometimes 1, sometimes 4") The cron job stops processing remaining users after hitting an orphaned record Backup log (/var/log/backup.log) shows NoneType errors instead of successful backups --- Root Cause Analysis Issue 1: Orphaned BackupList Records (Primary Bug) Location: Database / User deletion workflow When a user is deleted from Django admin: User is removed from auth_user table BackupList records with userid=<deleted_user_id> remain in database These are "orphaned records" - they reference non-existent users Verification command: cd /usr/local/lsws/Example/html/mypanel /root/venv/bin/python manage.py shell -c " from users.models import BackupList from django.contrib.auth.models import User valid_user_ids = User.objects.values_list('id', flat=True) orphaned = BackupList.objects.exclude(userid__in=valid_user_ids) print(f'Orphaned records: {orphaned.count()}') " Issue 2: No None Check in create_backup() (Code Bug) File: panel_setup/mypanel/users/database.py Line: 1109-1110 def create_backup(userid, backup_record): username = get_user_data_by_id(userid).get('username') # CRASH HERE When get_user_data_by_id(userid) returns None (user doesn't exist), calling .get('username') raises: AttributeError: 'NoneType' object has no attribute 'get' Note: The try/except block starts AFTER this line, so the error propagates up and crashes the entire backup process. Issue 3: Similar Bug in Other Functions The same issue exists in: create_backup_xml() (line 1227-1228) create_backup_cpanel() (line 1475) --- Solutions Workaround (Manual Process) Before deleting a user: Go to admin panel → Backup settings Delete the backup schedule for that user Then delete the user This prevents orphaned records from being created. Cleanup Script (Remove Existing Orphaned Records) Create and run /root/scripts/cleanup_orphaned.sh: #!/bin/bash echo "=== Cleaning Orphaned Backup Records ===" cd /usr/local/lsws/Example/html/mypanel /root/venv/bin/python manage.py shell -c " from users.models import BackupList from django.contrib.auth.models import User valid = list(User.objects.values_list('id', flat=True)) orphaned = BackupList.objects.exclude(userid__in=valid) count = orphaned.count() orphaned.delete() print(f'Deleted {count} orphaned records!') " Code Fix (Permanent Solution) Fix 1: Add None check in create_backup() def create_backup(userid, backup_record): user_data = get_user_data_by_id(userid) if not user_data: logger.error(f"User with ID {userid} not found - skipping backup") return False username = user_data.get('username') ... rest of function Fix 2: Same fix for create_backup_xml() and create_backup_cpanel() Fix 3: Add Django signal to prevent future orphans In users/models.py, add: from django.db.models.signals import pre_delete from django.dispatch import receiver from django.contrib.auth.models import User @receiver(pre_delete, sender=User) def cleanup_user_backups(sender, instance, **kwargs): """Automatically delete backup records when a user is deleted.""" BackupList.objects.filter(userid=instance.id).delete()