# Avatar Upload Debugging Guide Last Updated: 2025-08-29 ## Issue Summary The avatar upload functionality was experiencing file corruption during transmission from the frontend to the backend. PNG files were being corrupted where the PNG header `\x89PNG` was being replaced with UTF-8 replacement characters `\xef\xbf\xbdPNG`. ## Root Cause Analysis ### Next.js Proxy Issue (ACTUAL ROOT CAUSE) The primary issue was in the Next.js API proxy route that converts binary FormData to text: **File:** `/Users/talor/dyad-apps/thrillwiki-real/src/app/api/[...path]/route.ts` 1. **Problematic code:** ```typescript body = await clonedRequest.text(); // This corrupts binary data! ``` 2. **Why this causes corruption:** - FormData containing binary image files gets converted to UTF-8 text - Binary bytes like `\x89` (PNG signature) become UTF-8 replacement characters `\xef\xbf\xbd` - This mangles the file data before it even reaches the backend ## Solutions Implemented ### Next.js Proxy Fix (PRIMARY FIX) **File:** `/Users/talor/dyad-apps/thrillwiki-real/src/app/api/[...path]/route.ts` Fixed the proxy to preserve binary data instead of converting to text: ```typescript // BEFORE (problematic) body = await clonedRequest.text(); // Corrupts binary data! // AFTER (fixed) const arrayBuffer = await clonedRequest.arrayBuffer(); body = new Uint8Array(arrayBuffer); // Preserves binary data ``` **Why this works:** - `arrayBuffer()` preserves the original binary data - `Uint8Array` maintains the exact byte sequence - No UTF-8 text conversion that corrupts binary files ### Backend Cleanup **File:** `/Users/talor/thrillwiki_django_no_react/backend/apps/api/v1/serializers/accounts.py` Simplified the avatar validation to basic file validation only: ```python # Removed complex corruption repair logic # Now just validates file size, format, and dimensions with PIL def validate_avatar(self, value): # Basic file validation only # Let Cloudflare Images handle the rest ``` ## Technical Details ### API Flow 1. **Frontend:** `AvatarUploader` → `useAuth.uploadAvatar()` → `accountApi.uploadAvatar(file)` 2. **Next.js Proxy:** Preserves binary data using `arrayBuffer()` instead of `text()` 3. **Backend:** `AvatarUploadView` → `AvatarUploadSerializer.validate_avatar()` → Cloudflare Images API ## Testing ### Manual Testing Steps 1. Select a PNG image file in the avatar uploader 2. Upload the file 3. Verify the upload succeeds without corruption 4. Check that the avatar displays correctly ## Prevention ### Frontend Best Practices - Always pass `FormData` objects directly to API calls - Avoid extracting and re-wrapping files unnecessarily - Use proper file validation on the client side ### Backend Best Practices - Use Django's proper file upload classes (`InMemoryUploadedFile`, `TemporaryUploadedFile`) - Implement robust file validation and corruption detection - Provide detailed logging for debugging file upload issues ## Related Files ### Frontend - `/Users/talor/dyad-apps/thrillwiki-real/src/components/profile/avatar-uploader.tsx` - `/Users/talor/dyad-apps/thrillwiki-real/src/hooks/use-auth.tsx` - `/Users/talor/dyad-apps/thrillwiki-real/src/lib/api.ts` ### Backend - `/Users/talor/thrillwiki_django_no_react/backend/apps/api/v1/serializers/accounts.py` - `/Users/talor/thrillwiki_django_no_react/backend/apps/api/v1/accounts/views.py` - `/Users/talor/thrillwiki_django_no_react/backend/apps/accounts/services.py` ## Status ✅ **RESOLVED** - File corruption issue fixed in Next.js proxy ✅ **CLEANED UP** - Removed unnecessary corruption repair code from backend ✅ **DOCUMENTED** - Comprehensive debugging guide created The avatar upload functionality should now work correctly without file corruption. The Next.js proxy properly preserves binary data, and the backend performs basic file validation only.