This is an automated email from the ASF dual-hosted git repository. vatamane pushed a commit to branch 3.3.x-pending-changes-3.3.3 in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 4188889b8e5262f7bb65f244fdcf5d74c66ac541 Author: Nick Vatamaniuc <vatam...@gmail.com> AuthorDate: Mon Jul 17 16:42:56 2023 -0400 Fix multipart parser "attachment longer than expected" error Previously, we used a stale `Waiting` list of workers instead of the updated `NewWaiting` one. Then, when we recursed back to the top in `maybe_send_data/1`, and tried to reply to all waiting clients, we re-sent the same block to the client. That client would then get more attachment blocks than it expected and would throw an `attachment longer than expected` error. At the API level this would manifest as an intermittent 400 (bad_request) HTTP error for multipart document + attachments PUTs. For the error to occur, a `{hello_from_writer, ...}` has to be recieved when we're in the bottom part of `maybe_send_data/1` in the couch_httpd_multipart parser. However, due to how CouchDB replicator skips over documents PUTs which generate 4xx errors, the effect was that these documents were skipped over during replication, with only a `doc_write_failures` statistic bump to indicate that something went wrong. There is a somewhat related issue for discussion whether that replicator behavior is desirable [1] [1] https://github.com/apache/couchdb/issues/4676. --- src/couch/src/couch_httpd_multipart.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/couch/src/couch_httpd_multipart.erl b/src/couch/src/couch_httpd_multipart.erl index 11ee6790e..80fc48a75 100644 --- a/src/couch/src/couch_httpd_multipart.erl +++ b/src/couch/src/couch_httpd_multipart.erl @@ -203,7 +203,7 @@ maybe_send_data({Ref, Chunks, Offset, Counters, Waiting}) -> end; {hello_from_writer, Ref, WriterPid} -> C2 = handle_hello(WriterPid, Counters), - maybe_send_data({Ref, NewChunks, NewOffset, C2, Waiting}); + maybe_send_data({Ref, NewChunks, NewOffset, C2, NewWaiting}); {get_bytes, Ref, X} -> C2 = update_writer(X, Counters), maybe_send_data({Ref, NewChunks, NewOffset, C2, [X | NewWaiting]})