HelloZeroNet/ZeroNet · warning · VerifyError

We have newer (Our: %s, Sent: %s)

Error message

We have newer (Our: %s, Sent: %s)

What it means

verifyFile raises VerifyError('We have newer (Our: X, Sent: Y)') when the site already holds a content.json for the same inner_path with a 'modified' timestamp greater than the one being verified. ZeroNet uses the modified timestamp as a conflict-resolution mechanism; an older update is rejected as stale. Note the two %s placeholders are both printed (message string lists three format slots' worth of text but supplies two args).

Source

Thrown at src/Content/ContentManager.py:950

            from Crypt import CryptBitcoin
            try:
                if type(file) is dict:
                    new_content = file
                else:
                    try:
                        if sys.version_info.major == 3 and sys.version_info.minor < 6:
                            new_content = json.loads(file.read().decode("utf8"))
                        else:
                            new_content = json.load(file)
                    except Exception as err:
                        raise VerifyError("Invalid json file: %s" % err)
                if inner_path in self.contents:
                    old_content = self.contents.get(inner_path, {"modified": 0})
                    # Checks if its newer the ours
                    if old_content["modified"] == new_content["modified"] and ignore_same:  # Ignore, have the same content.json
                        return None
                    elif old_content["modified"] > new_content["modified"]:  # We have newer
                        raise VerifyError(
                            "We have newer (Our: %s, Sent: %s)" %
                            (old_content["modified"], new_content["modified"])
                        )
                if new_content["modified"] > time.time() + 60 * 60 * 24:  # Content modified in the far future (allow 1 day+)
                    raise VerifyError("Modify timestamp is in the far future!")
                if self.isArchived(inner_path, new_content["modified"]):
                    if inner_path in self.site.bad_files:
                        del self.site.bad_files[inner_path]
                    raise VerifyError("This file is archived!")
                # Check sign
                sign = new_content.get("sign")
                signs = new_content.get("signs", {})
                if "sign" in new_content:
                    del(new_content["sign"])  # The file signed without the sign
                if "signs" in new_content:
                    del(new_content["signs"])  # The file signed without the signs

                sign_content = json.dumps(new_content, sort_keys=True)  # Dump the json to string to remove whitepsace

View on GitHub (pinned to 454c0b2e7e)

Solutions

  1. Do nothing if you already have the newer content — this rejection is expected and harmless
  2. Force re-download from a newer peer (siteUpdate / reconnect to peers with the latest revision)
  3. If you are the site owner: re-publish with a fresh modified timestamp (now) so peers accept the update
  4. If the local copy is wrong/stuck, delete data/<site>/content.json and re-sync

Example fix

// before (site owner republishing with a manual stale timestamp)
{"modified": 1600000000, ...}
// after: set to current time before signing
content["modified"] = int(time.time()); signAndPublish(content)
Defensive patterns

Strategy: try-catch

Validate before calling

import json, time
new = json.load(open('new_content.json'))
old = json.load(open('data/<site>/content.json'))
if new.get('modified', 0) <= old.get('modified', 0):
    print('stale content: bump modified timestamp before publishing')

Try / catch

from Content.ContentManager import VerifyError
try:
    site.content_manager.isModified(inner_path, file)
except VerifyError as e:
    if str(e).startswith('We have newer'):
        pass  # already have a newer revision; safe to ignore
    else:
        raise

Prevention

When it happens

Trigger: isModified -> verifyFile receives a content.json whose modified timestamp is lower than self.contents[inner_path]['modified']; triggered when a peer pushes or you fetch an older revision, or when clocks differ and you already applied a newer update.

Common situations: Downloading from a stale/behind peer after you already got the latest revision; a site owner republished with a lower timestamp (clock rollback); merging site data where a newer content.json was already seeded from a tracker.

Related errors


AI-assisted analysis of HelloZeroNet/ZeroNet@454c0b2e7e (2026-09-02). Data as JSON: /api/errors/6e4d0d5cc20b6885. Report an issue: GitHub.