When uploading images to /answers/submit endpoint, you were getting:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 374: invalid start byte
Root Cause:
- Frontend was sending multipart/form-data with binary image files
- Backend was expecting JSON with base64-encoded image strings
- When validation failed, FastAPI tried to encode the binary data as UTF-8, causing the error
Changed the /answers/submit endpoint from:
@router.post("/submit", response_model=APIResponse)
async def submit_answer(answer: AnswerSubmit, ...):To:
@router.post("/submit", response_model=APIResponse)
async def submit_answer(
question_id: str = Form(...),
image: UploadFile = File(...), # ← Accept binary file directly
text_answer: str = Form(...),
gps_latitude: float = Form(...),
gps_longitude: float = Form(...),
gps_accuracy: float = Form(...),
verification_data: Optional[str] = Form(None), # ← JSON as string
authorization: str = Form(None),
...
):Key Changes:
- ✅ Accept
UploadFilefor binary image data - ✅ Accept form fields separately
- ✅ Parse verification_data as JSON string
- ✅ Convert binary to base64 inside endpoint
- ✅ Prevent binary data from appearing in error responses
Changed from sending JSON with base64:
const payload = {
question_id: questionId,
image_base64: verificationData.imageBase64, // ← Base64 string
text_answer: answerText,
...
};
const response = await apiCall('/answers/submit', {
method: 'POST',
body: JSON.stringify(payload)
});To sending multipart/form-data:
const formData = new FormData();
formData.append('question_id', questionId);
formData.append('image', verificationData.imageFile); // ← Binary file object
formData.append('text_answer', answerText);
formData.append('gps_latitude', verificationData.gps.latitude);
formData.append('gps_longitude', verificationData.gps.longitude);
formData.append('gps_accuracy', verificationData.gps.accuracy);
formData.append('verification_data', JSON.stringify(verificationJson));
const response = await fetch(`${API_URL}/answers/submit`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`
},
body: formData // ← Send FormData directly, no JSON.stringify
});Key Changes:
- ✅ Store File object instead of base64 string
- ✅ Create FormData object for multipart
- ✅ Append file directly (not encoded)
- ✅ Use
fetch()instead ofapiCall()to handle FormData properly - ✅ Browser automatically sets correct Content-Type header
Before: Binary JPEG bytes → Tried to encode as JSON → UnicodeDecodeError After: Binary file → Stored directly in multipart form → No encoding issues
- routes/answers.py - Updated
/answers/submitendpoint - frontend-html/submit-answer.js - Updated form submission logic
from fastapi import UploadFile, File, Form
import jsonRun the test script:
python test_multipart_upload.pyExpected output:
🧪 Testing Multipart Form Upload for /answers/submit
==================================================
1️⃣ Getting authentication token...
✅ Token: eyJ0eXAiOiJKV1QiLc...
2️⃣ Finding a question nearby...
✅ Question ID: uuid-here
3️⃣ Creating test image...
✅ Test image created (100x100px JPEG)
4️⃣ Preparing multipart form data...
✅ Form data prepared
5️⃣ Sending POST request to /answers/submit...
Status Code: 200
✅ SUCCESS!
Answer ID: answer-uuid
Message: Answer submitted and queued for ML verification
The fix ensures:
- ✅ Binary image data is NOT converted to text (avoids UnicodeDecodeError)
- ✅ Multipart form data is properly handled
- ✅ Verification data is correctly parsed as JSON
- ✅ ML pipeline still processes images in background
- ✅ Image is stored in Supabase and converted to base64 for ML processing
For friend's laptop (HTML/CSS/JS frontend):
- Update
frontend-html/submit-answer.js(already done ✅) - Ensure API_URL points to backend:
http://localhost:8000or deployed URL - No build step needed - just serve HTML files
For React frontend (if using later):
Similar changes needed in frontend/src/pages/SubmitAnswerPage.tsx
If you need to go back to base64 encoding:
- Revert routes/answers.py to accept
AnswerSubmitmodel - Change frontend to encode image as base64
- Frontend sends
JSON.stringify(payload)with base64 image
Status: ✅ Fixed and ready to test!