Multi-Hoster-Upload/tasks/todo.md
Administrator 0ba8bd3a2c fix(hosters): defensive null-payload guards in result parsers + 7 tests
When a hoster server replies with a body that JSON-parses to a
non-object (literal "null", a bare string, a number, a top-level
array), uploadFile's downstream code crashed:

  payload.msg          → TypeError on null
  payload.status       → TypeError on null
  config.parseResult() → TypeError inside parseDoodstreamResult
                         (payload.result) and parseByseResult
                         (payload.files / payload.result)

The user saw a confusing "Cannot read properties of null" instead of
a useful "server returned no JSON object". Found by deep-audit pass.

Fix in three places:

1. uploadFile (lib/hosters.js): after JSON.parse, normalise non-object
   payloads to {}. Subsequent `payload.X` accesses then return
   undefined and the existing fallback paths handle the empty case.

2. parseDoodstreamResult: defensive `payload && payload.result` so
   direct callers (tests, hypothetical future callers) get the same
   guarantee instead of relying on uploadFile to have normalised.

3. parseByseResult: same `payload || typeof payload !== 'object'`
   short-circuit at entry, plus null-checks on `f` (the first files
   entry) so a server returning [null] in files doesn't crash either.

Tests: 7 new unit tests covering null/undefined/string/number/array
payloads, malformed files entries, the fileRejected/accountError
classification (regression-pinning the 3.1.4 phrasing tweaks), and
the valid-filecode happy path. 126/126 green.
2026-04-28 10:12:32 +02:00

4.0 KiB

Verbesserungs-Loop — open items

Released

  • 3.3.0 — Performance-Fixes (queue-cap, sort-throttle, history-delegation, recent-cap) + Log-Recovery
  • 3.3.1 — removeFromQueueOnDone coalesced via microtask (kein O(N²) mehr bei done-Bursts)
  • 3.3.2 — fileuploader.log Auto-Rotation bei 50 MB (max 3 Backups: .1 .2 .3)
  • 3.3.3 — _jobLogCollector Cap auf 1000 tracked jobs (FIFO-eviction beim Überschreiten)
  • 3.3.4 — applyQueueSelectionClasses + applyRecentSelectionClasses nutzen getElementsByClassName (live HTMLCollection statt querySelectorAll re-query bei jedem Klick)
  • 3.3.5 — Log-Rotation extrahiert nach lib/log-rotation.js + 10 neue Unit-Tests (cap, shift, eviction, idempotency, maxBackups=1, invalid input, no-extension)
  • 3.3.6 — CSS .queue-row transition nur noch auf :hover (kein 150ms compositor-tween bei status-flips)
  • 3.3.7 — _sessionTrackedJobs/_sessionDoneJobs werden bei handleBatchDone gegen current queueJobs geprunt (no more unbounded session memory growth across batches)
  • 3.3.8 — queue-cap-prune-Logik nach lib/queue-prune.js extrahiert (dual-environment: Node + Browser-global) + 10 Unit-Tests (insertion-order, limit=0, malformed entries, large-queue 5000-job sweep)
  • 3.3.9 — Throttled-Cache nach lib/throttled-cache.js extrahiert (von sortQueueJobs dynamic-throttle genutzt) + 12 Unit-Tests (TTL-Boundary, identity-tracking, fake-clock, peek/clear, refreshMs=0, large-input)
  • 3.3.10 — npm audit fix (non-breaking): 4 vulnerabilities geschlossen (16 → 12), nur Lock-file Update
  • 3.3.11 — Patch-Bumps eslint 10.1→10.2, undici 7.24→7.25, ws 8.19→8.20 (semver-compatible)
  • 3.3.12 — Race condition fix: uploadManager = null in batch-done clobberte einen frisch gespawnten Manager wenn user mid-await neuen batch startete (deep-audit finding HIGH-1)
  • 3.3.13 — save-global-settings-sync reportet jetzt returnValue=false bei Fehlern + debugLog statt silent swallow; TOCTOU bei .bak-Refresh in beiden Pfaden (main.js + lib/config-store.js _atomicWrite) entkoppelt: bak-Read-Failure failt nicht mehr den ganzen Save (deep-audit findings HIGH-2 + MED-4)
  • 3.3.14 — Parser-null-payload guard: uploadFile normalisiert payload zu {} falls JSON.parse('null') o.ä.; parseDoodstreamResult + parseByseResult haben defensive guards für direct callers + 7 neue Unit-Tests (null/non-object, malformed entries, fileRejected/accountError flips, valid filecode happy path)

Open items (priorisiert)

Stabilität (neu aus deep-audit)

  • Cancellation latency in retry-loop's account-rotation block (lib/upload-manager.js:680-792) — re-check signal.aborted after each await.

Code-Qualität (deferred)

  • removeFromQueueOnDone microtask-coalesce (3.3.1) — Microtask-Timing schwer zu testen ohne fake-timer setup
  • 12 weitere Vulnerabilities (10 high, 2 low) in electron-builder dev-chain — bräuchten npm audit fix --force mit Major-Bump electron-builder@26.8.1 (breaking). Skip bis User explizit ein Major-Update erlaubt.

Loop-Status

Alle initial im 3.3.0-Audit identifizierten Items sind nun adressiert. Beide verbliebenen open items sind explizit deferred (microtask-fake-timer-Setup ist Refactor, audit-fix --force ist Major-Bump und braucht User-OK).

Iteration 11 (skipped, no release): kein nicht-deferred Item übrig. Loop läuft idle weiter — bei nächstem Cron-Tick prüft er erneut, falls inzwischen neue Issues aufgetaucht sind.

Sinnvolle nächste Schritte für den User:

  • "Loop stop" wenn nichts mehr passieren soll (CronDelete 01e33ae1)
  • "Major bump genehmigt" für npm audit fix --force (closes 12 deferred vulns, bumpt electron-builder@26)
  • Neue konkrete User-Beschwerden / Bug-Reports
  • Manuelle Anweisung was als nächstes interessant wäre

Loop-Notes

  • Cron-Job 01e33ae1 läuft alle 30min (:07/:37), Session-only.
  • Pro Iteration: GENAU EIN Issue. Auto-Release bei grünen Tests. Boundary: keine Features, keine Major-Refactors.