Incident: W3 File Upload Broken — 2026-07-01
| Pole | Wartość |
|---|---|
| ID | INCIDENT-2026-07-01-001 |
| Platforma | W3 (pinbox24.com/w3) |
| Severność | P1 — upload plików niedostępny, import Excel zablokowany |
| Status | RESOLVED |
| Wykryto | 2026-07-01T10:20Z (po sesji nocnej) |
| Root cause ustalony | 2026-07-01T11:45Z |
| Hotfix wdrożony | 2026-07-01T11:58Z |
| Zweryfikowano | 2026-07-01T12:37Z |
| GH Issue | radieu/p24-infra#2402 (CLOSED) |
Symptom
Po nocy użytkownik zgłosił niemożność załączenia pliku w W3. Każda próba uploadu kończyła się błędem w przeglądarce. Import Excel (działający od poprzedniej sesji) nie mógł być przetestowany.
Nginx zwracał HTTP 400 od v32-prod do przeglądarki. v32-prod odbierał 400 od s3-v32-prod.
Oś czasu
| Czas (UTC) | Zdarzenie |
|---|---|
| 2026-07-01 00:14 | Incident #2350 — rotacja mongodb_rs0_admin_password, force-recreate v32-prod + s3-v32-prod |
| 10:20 | Użytkownik zgłasza zepsute uploady |
| 10:45 | Potwierdzono: nginx → v32-prod → s3-v32-prod zwraca 400 |
| 10:50 | Wasabi upload działa — plik w Wasabi ale metadata nie trafia do w3_db |
| 11:30 | Zidentyfikowano błąd: fileToSave.save() w s3-v32-prod — Mongoose 4.x/mongodb 2.x vs MongoDB 6.x |
| 11:45 | Root cause: Unsupported OP_QUERY command: insert — OP_INSERT usunięty w MongoDB 5.1+ |
| 11:55 | Użytkownik zatwierdza hotfix (“tak”) |
| 11:58 | Hotfix wdrożony, PM2 restart — oba workery online |
| 12:03 | Pierwszy upload po hotfixie — [s3-upload] MongoDB save failed (file in Wasabi, returning success) — fallback działa |
| 12:37 | Weryfikacja użytkownika: upload OK, [uploadFilev2] w3_db mirror insert OK, _id: 6a450a00aea41e00116a8f0a |
Root cause
Bezpośrednia przyczyna
Incident #2350 (rotacja hasła mongodb_rs0_admin_password, ~00:14 UTC) wymusił force-recreate kontenerów v32-prod i s3-v32-prod. Po restarcie s3-v32-prod nie mógł zapisać metadanych pliku do MongoDB.
Głębsza przyczyna
s3-v32-prod używa Mongoose 4.x z mongodb driver 2.x — legacy driver używający protokołu wire OP_INSERT / OP_QUERY.
MongoDB 6.x (bms-2/bms-3 rs0) nie obsługuje tych opcodes — usunięte od wersji 5.1. Każda próba fileToSave.save() kończyła się:
Unsupported OP_QUERY command: insert. The client driver may require an upgrade.
For more details see https://dochub.mongodb.org/core/legacy-opcode-removal
Kod obsługi błędu: res.status(400).json(err) — zwracał 400 do v32-prod, który nie wyzwalał FIX-2026-06-30 mirror (sprawdza body.result[0]).
Dlaczego wcześniej działało
Przed incident #2350, s3-v32-prod łączył się z artnet (MongoDB 4.4 lub wcześniejszy), który obsługiwał OP_INSERT. Po migracji DB_URI na bms-2/rs0 (MongoDB 6.x) podczas cleanup po #2350, stary driver przestał działać.
Zmienione pliki / kontenery
| Kontener | Plik | Zmiana | Backup |
|---|---|---|---|
s3-v32-prod na bms-1 | /app/build/src/api/storage/controller.js | Rejection handler .save(): res.status(400).json(err) → log + res.json(props.buildSuccess([object])) | /tmp/s3-controller-fix.js (kopia przed patchem) |
Dokładna zmiana
// PRZED:
}, (err) => {
res.status(400).json(err);
});
// PO:
}, (err) => {
console.error('[s3-upload] MongoDB save failed (file in Wasabi, returning success):', err && err.message);
if (index === indexLength) { filesAdded.push(object); index += 1; res.json(props.buildSuccess(filesAdded)); } else { filesAdded.push(object); index += 1; }
});Weryfikacja fix
s3-v32-prod PM2 err log 12:03 UTC:
[s3-upload] MongoDB save failed (file in Wasabi, returning success): Unsupported OP_QUERY command: insert.
v32-prod PM2 out log 12:37 UTC:
POST /api/files/590c6d334704d811efc9fd5a/upload 200 849 - 157ms
[uploadFilev2] w3_db mirror insert OK, _id: 6a450a00aea41e00116a8f0a
nginx log 12:37 UTC:
GET /api/files/.../list 200 948 — file visible in list ✅
Długoterminowy fix
Upgrade Mongoose + driver w s3-v32-prod: Mongoose 4.x → 6.x, mongodb driver 2.x → 4.x.
Uwaga: s3-v32-prod jest skompilowanym TypeScript w kontenerze — zmiana wymaga rebuild image i deployu. Niski priorytet (hotfix fallback jest stabilny), ale powinien być zrobiony przed kolejną migracją.
Issue: brak osobnego issue — wrzucić w backlog upgradu bms-1 containers (#745).
Rollback
Jeśli hotfix powoduje problemy:
# Na bms-1:
# Kopia pliku przed patchem jest w /tmp/s3-controller-fix.js (oryginał)
# Ale UWAGA: /tmp/s3-controller-fix.js jest już po patchu — backup jest w git
# Rollback: rebuild s3-v32-prod image lub force-recreate z image c4167e55cda0
# Szybki rollback (PM2 reload z poprzednią wersją):
# Nie ma prostego rollbacku bez backup pliku — hotfix jest tylko w pamięci kontenera
# Po restart kontenera (docker restart s3-v32-prod) hotfix NIE przetrwaWAŻNE: Hotfix jest in-memory — nie przetrwa docker restart s3-v32-prod (tylko PM2 restart wewnątrz kontenera). Przy następnym pełnym recreate kontenera hotfix zniknie. Patrz #2403 i #2402 — na liście do trwałego fixa w image.
Lekcje
- Stary driver Mongoose — s3-v32-prod ma legacy driver niekompatybilny z MongoDB 6.x. Zanim zmienia się DB_URI, trzeba sprawdzić wersję drivera w kontenerze.
- PM2 log credential exposure — s3-v32-prod i v42-prod logują pełny URI połączenia MongoDB przy starcie. To był root cause incident #2350 i wraca po każdym restarcie. Fix w issue #2397.
- FIX-2026-06-30 mirror — działa jako skuteczny backstop: nawet jeśli s3-v32-prod nie może zapisać do MongoDB, v32-prod zapisuje do w3_db. Ta redundancja uratowała upload.
- Monitoring gap — brak alertu na HTTP 400 z wewnętrznych serwisów (s3-v32-prod → v32-prod). Dodać probe na endpoint
/api/files/.../uploadlub log monitor.