{"record":{"id":"6e4d0d5cc20b6885","repo":"HelloZeroNet/ZeroNet","slug":"we-have-newer-our-s-sent-s","errorCode":null,"errorMessage":"We have newer (Our: %s, Sent: %s)","messagePattern":"We have newer \\(Our: (.+?), Sent: (.+?)\\)","errorType":"validation","errorClass":"VerifyError","httpStatus":null,"severity":"warning","filePath":"src/Content/ContentManager.py","lineNumber":950,"sourceCode":"            from Crypt import CryptBitcoin\n            try:\n                if type(file) is dict:\n                    new_content = file\n                else:\n                    try:\n                        if sys.version_info.major == 3 and sys.version_info.minor < 6:\n                            new_content = json.loads(file.read().decode(\"utf8\"))\n                        else:\n                            new_content = json.load(file)\n                    except Exception as err:\n                        raise VerifyError(\"Invalid json file: %s\" % err)\n                if inner_path in self.contents:\n                    old_content = self.contents.get(inner_path, {\"modified\": 0})\n                    # Checks if its newer the ours\n                    if old_content[\"modified\"] == new_content[\"modified\"] and ignore_same:  # Ignore, have the same content.json\n                        return None\n                    elif old_content[\"modified\"] > new_content[\"modified\"]:  # We have newer\n                        raise VerifyError(\n                            \"We have newer (Our: %s, Sent: %s)\" %\n                            (old_content[\"modified\"], new_content[\"modified\"])\n                        )\n                if new_content[\"modified\"] > time.time() + 60 * 60 * 24:  # Content modified in the far future (allow 1 day+)\n                    raise VerifyError(\"Modify timestamp is in the far future!\")\n                if self.isArchived(inner_path, new_content[\"modified\"]):\n                    if inner_path in self.site.bad_files:\n                        del self.site.bad_files[inner_path]\n                    raise VerifyError(\"This file is archived!\")\n                # Check sign\n                sign = new_content.get(\"sign\")\n                signs = new_content.get(\"signs\", {})\n                if \"sign\" in new_content:\n                    del(new_content[\"sign\"])  # The file signed without the sign\n                if \"signs\" in new_content:\n                    del(new_content[\"signs\"])  # The file signed without the signs\n\n                sign_content = json.dumps(new_content, sort_keys=True)  # Dump the json to string to remove whitepsace","sourceCodeStart":932,"sourceCodeEnd":968,"githubUrl":"https://github.com/HelloZeroNet/ZeroNet/blob/454c0b2e7e000fda7000cba49027541fbf327b96/src/Content/ContentManager.py#L932-L968","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Do nothing if you already have the newer content — this rejection is expected and harmless","Force re-download from a newer peer (siteUpdate / reconnect to peers with the latest revision)","If you are the site owner: re-publish with a fresh modified timestamp (now) so peers accept the update","If the local copy is wrong/stuck, delete data/<site>/content.json and re-sync"],"exampleFix":"// before (site owner republishing with a manual stale timestamp)\n{\"modified\": 1600000000, ...}\n// after: set to current time before signing\ncontent[\"modified\"] = int(time.time()); signAndPublish(content)","handlingStrategy":"try-catch","validationCode":"import json, time\nnew = json.load(open('new_content.json'))\nold = json.load(open('data/<site>/content.json'))\nif new.get('modified', 0) <= old.get('modified', 0):\n    print('stale content: bump modified timestamp before publishing')","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).startswith('We have newer'):\n        pass  # already have a newer revision; safe to ignore\n    else:\n        raise","preventionTips":["Always set modified = int(time.time()) immediately before signing","Sync clock via NTP on publishing machines","Ignore 'We have newer' rejections during normal peer sync — they are expected"],"tags":["zeronet","content-verification","timestamp-conflict","sync"],"backgroundTag":"stale-content-timestamp","analyzedSha":"454c0b2e7e000fda7000cba49027541fbf327b96","analyzedAt":"2026-09-02T19:46:57.278Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}