HelloZeroNet/ZeroNet · error · VerifyError
Invalid hash
Error message
Invalid hash
What it means
verifyPiece() hashes the downloaded piece with sha512 and compares it against the expected digest stored in the piecemap. A mismatch means the piece data is corrupt, tampered with, or does not match the published piecemap, so verification fails with VerifyError('Invalid hash').
Source
Thrown at plugins/Bigfile/BigfilePlugin.py:399
return back
def getPiecemap(self, inner_path):
file_info = self.site.content_manager.getFileInfo(inner_path)
piecemap_inner_path = helper.getDirname(file_info["content_inner_path"]) + file_info["piecemap"]
self.site.needFile(piecemap_inner_path, priority=20)
piecemap = Msgpack.unpack(self.site.storage.open(piecemap_inner_path, "rb").read())[helper.getFilename(inner_path)]
piecemap["piece_size"] = file_info["piece_size"]
return piecemap
def verifyPiece(self, inner_path, pos, piece):
try:
piecemap = self.getPiecemap(inner_path)
except Exception as err:
raise VerifyError("Unable to download piecemap: %s" % Debug.formatException(err))
piece_i = int(pos / piecemap["piece_size"])
if CryptHash.sha512sum(piece, format="digest") != piecemap["sha512_pieces"][piece_i]:
raise VerifyError("Invalid hash")
return True
def verifyFile(self, inner_path, file, ignore_same=True):
if "|" not in inner_path:
return super(ContentManagerPlugin, self).verifyFile(inner_path, file, ignore_same)
inner_path, file_range = inner_path.split("|")
pos_from, pos_to = map(int, file_range.split("-"))
return self.verifyPiece(inner_path, pos_from, file)
def optionalDownloaded(self, inner_path, hash_id, size=None, own=False):
if "|" in inner_path:
inner_path, file_range = inner_path.split("|")
pos_from, pos_to = map(int, file_range.split("-"))
file_info = self.getFileInfo(inner_path)
# Mark piece downloadedView on GitHub (pinned to 454c0b2e7e)
Solutions
- Delete the affected file from the site data directory and re-download it from other peers
- Verify with multiple peers — if only one serves bad data, blacklist/mute that peer and refetch
- If you are the site owner: repack the big file and re-sign content.json so piecemap hashes match the current file
- Check that pos passed to verifyPiece is piece-aligned (int(pos / piece_size) must be the intended piece index)
Example fix
// before verifyPiece(inner_path, pos, piece) # pos from a stale/offset cursor // after piece_size = piecemap['piece_size'] assert pos % piece_size == 0, 'piece position not aligned' verifyPiece(inner_path, pos, piece)
Defensive patterns
Strategy: try-catch
Validate before calling
# detect file-modified-after-signing local_hash = CryptHash.sha512sum(open(file_path,'rb').read(), format='digest') expected = content_json['files'][inner_path]['sha512'] if local_hash != expected: re_pack_and_sign_site()
Try / catch
try:
site.verifyFile(inner_path, f)
except VerifyError as err:
if str(err) == 'Invalid hash':
delete_corrupted_piece_and_redownload(inner_path, pos)
else:
raise Prevention
- Never edit a big file after publishing without repacking and re-signing content.json
- Re-download pieces that fail verification from different peers
- Keep disk and network healthy (check SMART, use TLS/verified transports)
- Sanity-check piece positions are multiples of piece_size before hashing
When it happens
Trigger: A downloaded piece from a peer differs from the published sha512 digest: corrupted transfer, malicious peer serving wrong data, position math mismatch (pos not aligned to piece boundaries), or stale piecemap after the big file was modified but not repacked.
Common situations: Bit-flip corruption on disk/network; peer serving modified content; file edited/re-encoded after content.json/piecemap was signed; mismatched piece_size between the file and piecemap.
Related errors
AI-assisted analysis of HelloZeroNet/ZeroNet@454c0b2e7e (2026-09-02).
Data as JSON: /api/errors/6e362f9de1af2695.
Report an issue: GitHub.