Repository: borgbackup/borg

Issue:
more informative IntegrityError
IntegrityError should whenever possible include the chunk id where the problem was encountered.

Currently the error message just says that a specific problem happened on some chunk without nameing the chunk id. That does make debugging and fixing hard. With the chunk id there is at least some chance to drill down and come up with some fix.



Discussion:
Note:
- the IntegrityErrors raised from borg.repository are quite nice already (include segment/offset - but not object id yet). 
- the ones raised from borg.key are rather bare, no info at all yet.
- we should not call it _chunkid_ (not every object in the repo is a chunk), so, just _id_ or _object id_?

See PR #1034: "borg.key: include chunk id in exception msgs" - stay close to that to avoid merge conflicts?

https://github.com/borgbackup/borg/pull/1034/commits/bcdce91dfb2883c139011322a9e8086059fbe5c2


Resolving patch:
diff --git a/borg/key.py b/borg/key.py
--- a/borg/key.py
+++ b/borg/key.py
@@ -105,10 +105,10 @@ def encrypt(self, data):
 
     def decrypt(self, id, data):
         if data[0] != self.TYPE:
-            raise IntegrityError('Invalid encryption envelope')
+            raise IntegrityError('Chunk %s: Invalid encryption envelope' % bin_to_hex(id))
         data = self.compressor.decompress(memoryview(data)[1:])
         if id and sha256(data).digest() != id:
-            raise IntegrityError('Chunk id verification failed')
+            raise IntegrityError('Chunk %s: id verification failed' % bin_to_hex(id))
         return data
 
 
@@ -142,24 +142,24 @@ def encrypt(self, data):
     def decrypt(self, id, data):
         if not (data[0] == self.TYPE or
             data[0] == PassphraseKey.TYPE and isinstance(self, RepoKey)):
-            raise IntegrityError('Invalid encryption envelope')
+            raise IntegrityError('Chunk %s: Invalid encryption envelope' % bin_to_hex(id))
         hmac_given = memoryview(data)[1:33]
         hmac_computed = memoryview(HMAC(self.enc_hmac_key, memoryview(data)[33:], sha256).digest())
         if not compare_digest(hmac_computed, hmac_given):
-            raise IntegrityError('Encryption envelope checksum mismatch')
+            raise IntegrityError('Chunk %s: Encryption envelope checksum mismatch' % bin_to_hex(id))
         self.dec_cipher.reset(iv=PREFIX + data[33:41])
         data = self.compressor.decompress(self.dec_cipher.decrypt(data[41:]))
         if id:
             hmac_given = id
             hmac_computed = HMAC(self.id_key, data, sha256).digest()
             if not compare_digest(hmac_computed, hmac_given):
-                raise IntegrityError('Chunk id verification failed')
+                raise IntegrityError('Chunk %s: Chunk id verification failed' % bin_to_hex(id))
         return data
 
     def extract_nonce(self, payload):
         if not (payload[0] == self.TYPE or
             payload[0] == PassphraseKey.TYPE and isinstance(self, RepoKey)):
-            raise IntegrityError('Invalid encryption envelope')
+            raise IntegrityError('Manifest: Invalid encryption envelope')
         nonce = bytes_to_long(payload[33:41])
         return nonce
 


Test patch: