Skip to content

Fix/upload finish timeout - #100

Merged
alexanderoster merged 2 commits into
alexanderoster:developfrom
krixkrix:fix/upload-finish-timeout
Nov 5, 2026
Merged

alexanderoster merged 2 commits into
alexanderoster:developfrom
krixkrix:fix/upload-finish-timeout

Conversation

@krixkrix

@krixkrix krixkrix commented Nov 5, 2026

Copy link
Copy Markdown

Problem: uploads hanging at 100 % when the finish request is slow

Summary

/upload/finish makes the server hash the whole stream, so it takes longer the bigger the file is. On slow hardware (e.g. a Raspberry Pi) a large file takes more than the default 10 s request timeout. axios aborts the request, the empty .catch swallows the error, and the upload widget stays at 100 % forever.

 performJobUpload / performImageUpload
   POST /upload/                 (init)
   POST /upload/<uuid>/...       (chunks, no timeout)
-  POST /upload/finish           (default 10 s timeout)
+  POST /upload/finish           (no timeout, like the chunks)
   .catch(err)
-    err;                        // swallowed, widget hangs
+    uploadState.failUpload(err) // calls _onError, the frontend shows the failure

Second commit: an upload widget reuses one AMCUploadState, and the user can start a new upload while one is still running. Now that failures are reported, a late failure of the replaced upload would stop the newer one. failUpload() therefore only acts while its upload is the active one, the same check the chunk handlers already do.

AMCUpload.failUpload(reason)
if this upload is still the active one
itemState.failUpload(reason)

Only Client/core changes, so both the Vue2 and the Svelte client get the fix.

Evidence

New Client/tests/uploadFinish.test.mjs (node:test, no new dependencies), covering build and image uploads:

  • finish request is sent with timeout: 0
  • a failed finish calls _onError and ends the upload
  • a failed finish of a replaced upload leaves the newer upload running
  • Before (test file run against develop): 0/6 pass (timeout of 10000ms exceeded, newer upload aborted)
    After: 6/6 pass; the full cd Client/tests && npm test passes 14/14

Merge Danger

  • Client-only change with no API or data change. Revert the two commits to undo it.

  • If the server never answers, a finish request now waits indefinitely instead of failing after 10 s. The chunk requests already behave that way. Upload init, chunk and finish failures that used to be silently ignored now reach the widget's _onError.

/upload/finish makes the server hash the whole stream, so its duration
grows with the file size; on slow hardware such as a Raspberry Pi a
large file exceeds the default 10 s request timeout. axios then aborted
the request, the rejection was swallowed, and the upload widget stayed
at 100 % although the upload never completed.

The finish request of build and image uploads now runs without a
timeout, like the chunk POSTs. A failed init, chunk or finish request
calls the new AMCUploadState.failUpload(), which invokes _onError, so
the frontend shows the failure instead of hanging.
An upload widget reuses one AMCUploadState, and the user can start a new
upload while one is still running; the new upload takes over with a new
upload ID. A failing request of the replaced upload (e.g. a finish for a
3MF that does not parse) then reset the upload ID and fired _onError,
which silently stopped the newer upload.

AMCUpload.failUpload() now only acts while its upload is the active one,
as the chunk handlers already check.
@alexanderoster
alexanderoster merged commit f19f9b3 into alexanderoster:develop Nov 5, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants