{"record":{"id":"623e63af6cbc6348","repo":"HelloZeroNet/ZeroNet","slug":"invalid-hash-623e63","errorCode":null,"errorMessage":"Invalid hash","messagePattern":"Invalid hash","errorType":"validation","errorClass":"VerifyError","httpStatus":null,"severity":"error","filePath":"src/Content/ContentManager.py","lineNumber":1012,"sourceCode":"                            valid_signs += CryptBitcoin.verify(sign_content, address, signs[address])\n                        if valid_signs >= signs_required:\n                            break  # Break if we has enough signs\n                    if valid_signs < signs_required:\n                        raise VerifyError(\"Valid signs: %s/%s\" % (valid_signs, signs_required))\n                    else:\n                        return self.verifyContent(inner_path, new_content)\n                else:  # Old style signing\n                    raise VerifyError(\"Invalid old-style sign\")\n\n            except Exception as err:\n                self.log.warning(\"%s: verify sign error: %s\" % (inner_path, Debug.formatException(err)))\n                raise err\n\n        else:  # Check using sha512 hash\n            file_info = self.getFileInfo(inner_path)\n            if file_info:\n                if CryptHash.sha512sum(file) != file_info.get(\"sha512\", \"\"):\n                    raise VerifyError(\"Invalid hash\")\n\n                if file_info.get(\"size\", 0) != file.tell():\n                    raise VerifyError(\n                        \"File size does not match %s <> %s\" %\n                        (inner_path, file.tell(), file_info.get(\"size\", 0))\n                    )\n\n                return True\n\n            else:  # File not in content.json\n                raise VerifyError(\"File not in content.json\")\n\n    def optionalDelete(self, inner_path):\n        self.site.storage.delete(inner_path)\n\n    def optionalDownloaded(self, inner_path, hash_id, size=None, own=False):\n        if size is None:\n            size = self.site.storage.getSize(inner_path)","sourceCodeStart":994,"sourceCodeEnd":1030,"githubUrl":"https://github.com/HelloZeroNet/ZeroNet/blob/454c0b2e7e000fda7000cba49027541fbf327b96/src/Content/ContentManager.py#L994-L1030","documentation":"verifyFile raises VerifyError('Invalid hash') when verifying a regular (non-content.json) file: the file's sha512 (CryptHash.sha512sum) does not match the 'sha512' recorded for it in its parent content.json (via getFileInfo). This guarantees file integrity — the downloaded file differs from what the signed content.json declares.","triggerScenarios":"isModified -> verifyFile for a normal file: getFileInfo finds file_info from the site's content.json, and CryptHash.sha512sum(file) != file_info['sha512'] — the downloaded bytes are corrupt, modified, or the content.json hash entry doesn't match the local file.","commonSituations":"Bit-flip corruption during transfer, a peer serving tampered files, a locally modified file without re-publishing (hash in content.json now stale), or publishing files after signing content.json so hashes don't match.","solutions":["Delete the local file (data/<site>/<inner_path>) and re-download it from other peers","If you modified the file locally, re-publish the site so content.json is regenerated with new sha512 hashes","Verify manually: python -c \"import hashlib;print(hashlib.sha512(open('file','rb').read()).hexdigest())\" and compare to content.json","Check disk health if corruption recurs repeatedly"],"exampleFix":"// before: changed index.html without re-signing content.json\n{\"files\": {\"index.html\": {\"sha512\": \"OLDHASH\"}}}\n// after: re-sign so hashes update\nsite_manager.getSite(address).signContent(privatekey)  // then publish","handlingStrategy":"validation","validationCode":"import hashlib, json\ncontent = json.load(open('data/<site>/content.json'))\npath = 'index.html'\nexpected = content['files'][path]['sha512']\nactual = hashlib.sha512(open('data/<site>/' + path, 'rb').read()).hexdigest()\nassert actual == expected, 'file hash mismatch — re-download or re-publish'","typeGuard":null,"tryCatchPattern":"from Content.ContentManager import VerifyError\ntry:\n    site.content_manager.isModified(inner_path, file)\nexcept VerifyError as e:\n    if str(e) == 'Invalid hash':\n        os.remove('data/<site>/' + inner_path); site.needFile(inner_path)  # re-fetch\n    else:\n        raise","preventionTips":["Re-sign content.json after every file edit (hashes must match)","Re-download any file failing verification before retrying","Investigate disk/network health if corruption repeats"],"tags":["zeronet","hash-mismatch","integrity","content-verification"],"backgroundTag":"hash-mismatch","analyzedSha":"454c0b2e7e000fda7000cba49027541fbf327b96","analyzedAt":"2026-09-02T19:46:57.278Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}