HelloZeroNet/ZeroNet · error · VerifyError
Invalid old-style sign
Error message
Invalid old-style sign
What it means
verifyFile raises VerifyError('Invalid old-style sign') when the content.json does not use the modern multi-signature layout (no valid signers/signs structure could be processed) and falls into the legacy 'old style signing' branch, which ZeroNet no longer accepts here. Old-style content.json had a single 'sign' made over a differently-serialized body; such files must be re-signed with the current scheme.
Source
Thrown at src/Content/ContentManager.py:1002
signers_data = "%s:%s" % (signs_required, ",".join(valid_signers))
if not CryptBitcoin.verify(signers_data, self.site.address, new_content["signers_sign"]):
raise VerifyError("Invalid signers_sign!")
if inner_path != "content.json" and not self.verifyCert(inner_path, new_content): # Check if cert valid
raise VerifyError("Invalid cert!")
valid_signs = 0
for address in valid_signers:
if address in signs:
valid_signs += CryptBitcoin.verify(sign_content, address, signs[address])
if valid_signs >= signs_required:
break # Break if we has enough signs
if valid_signs < signs_required:
raise VerifyError("Valid signs: %s/%s" % (valid_signs, signs_required))
else:
return self.verifyContent(inner_path, new_content)
else: # Old style signing
raise VerifyError("Invalid old-style sign")
except Exception as err:
self.log.warning("%s: verify sign error: %s" % (inner_path, Debug.formatException(err)))
raise err
else: # Check using sha512 hash
file_info = self.getFileInfo(inner_path)
if file_info:
if CryptHash.sha512sum(file) != file_info.get("sha512", ""):
raise VerifyError("Invalid hash")
if file_info.get("size", 0) != file.tell():
raise VerifyError(
"File size does not match %s <> %s" %
(inner_path, file.tell(), file_info.get("size", 0))
)
return TrueView on GitHub (pinned to 454c0b2e7e)
Solutions
- Re-sign the content.json with the current signing scheme using CryptBitcoin.sign over the correct sign_content and place it in content['sign'][address] (single-signer modern format)
- Use the site owner's private key matching the site address
- Update your ZeroNet client and republish the site (Site:sign) so the content.json is regenerated in the accepted format
Example fix
// before: legacy layout
{"sign": "SINGLE_SIG_STRING", ...}
// after: modern layout
{"sign": {"<site_address>": "<sig>"}, ...} // signed via CryptBitcoin.sign(sign_content, privatekey) Defensive patterns
Strategy: validation
Validate before calling
import json
content = json.load(open('content.json'))
sign = content.get('sign')
if isinstance(sign, str):
raise ValueError('legacy single-string sign detected; re-sign with modern format')
if not isinstance(sign, dict) and not content.get('signs'):
raise ValueError('no valid signature structure found') Type guard
def has_modern_sign(content):
sign = content.get('sign')
return isinstance(sign, dict) and len(sign) > 0 Try / catch
from Content.ContentManager import VerifyError
try:
site.content_manager.isModified(inner_path, file)
except VerifyError as e:
if str(e) == 'Invalid old-style sign':
migrate_and_resign(site, privatekey) # republish with modern signing
else:
raise Prevention
- Re-sign any content.json predating the multi-sign scheme
- Use current ZeroNet tooling (Site:sign) to generate signatures
- Never hand-write the sign field; always generate with CryptBitcoin.sign
When it happens
Trigger: isModified -> verifyFile: the new-style branch (signers/signs) is not taken — e.g. content lacks 'signs' or the sign-content reconstruction fails — and execution reaches the else branch labeled 'Old style signing', which unconditionally raises.
Common situations: Very old sites whose content.json was signed years ago with the legacy format and never re-signed; hand-crafted content.json missing the 'signs' dict; migration of a site from an old ZeroNet version without re-publishing.
Related errors
- Invalid signers_sign!
- Valid signs: %s/%s
- Includes not allowed
- Invalid json file: %s
- We have newer (Our: %s, Sent: %s)
AI-assisted analysis of HelloZeroNet/ZeroNet@454c0b2e7e (2026-09-02).
Data as JSON: /api/errors/ef43470d065a1604.
Report an issue: GitHub.