You've identified a bug. When updating. TotalBytesToTransfer gets set incorrectly. Actually the broken code is setting TotalBytesToTransfer to the size of the compressed bytestream for an entry. But there are metadata that need to be transferred,
too, when updating a zip file. This accounts for the difference of 59 bytes, or 122 bytes, or 137 bytes in your examples.

In general, there's no guarantee that BytesTransferred will be less than or equal to TotalBytesToTransfer. In some cases, when creating new zip files, TotalBytesToTransfer will be zero. This can happen when zipping up from a forward-only
(non seekable) stream. This is not happening in your case! In your case you have a filesystem file, and it is seekable. In that case, when the bug is fixed, you will be able to rely on the fact that BytesTransferred <= TotalBytesToTransfer.

Some additional detail:
The Save() takes a different code path when updating, versus creating a zip the first time. When creating a zip entry, the progress event tracks only the file data, not metadata. The "denominator" in this case - the TotalBytesToTransfer
- is set to the size of the uncompressed data. in your case, the length of the file. When calling Save() on an updated zip, any entry that is unchanged is just transferred from the original zip file to the new one. The update copies the entire zipentry
- header, compressed bytes and footer. But it was using only the size of the compressed bytestream as the TotalBytesToTransfer.