{"record":{"id":"4cd6a4897e1102d4","repo":"HelloZeroNet/ZeroNet","slug":"invalid-content-json-file-s","errorCode":null,"errorMessage":"Invalid content.json file: %s","messagePattern":"Invalid content\\.json file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/Ui/UiWebsocket.py","lineNumber":415,"sourceCode":"                for key, val in stats.items():\n                    if key.startswith(\"num_\"):\n                        back[tracker][key] = back[tracker].get(key, 0) + val\n                    elif is_latest_data:\n                        back[tracker][key] = val\n\n        return back\n\n    # Sign content.json\n    def actionSiteSign(self, to, privatekey=None, inner_path=\"content.json\", remove_missing_optional=False, update_changed_files=False, response_ok=True):\n        self.log.debug(\"Signing: %s\" % inner_path)\n        site = self.site\n        extend = {}  # Extended info for signing\n\n        # Change to the file's content.json\n        file_info = site.content_manager.getFileInfo(inner_path)\n        if not inner_path.endswith(\"content.json\"):\n            if not file_info:\n                raise Exception(\"Invalid content.json file: %s\" % inner_path)\n            inner_path = file_info[\"content_inner_path\"]\n\n        # Add certificate to user files\n        is_user_content = file_info and (\"cert_signers\" in file_info or \"cert_signers_pattern\" in file_info)\n        if is_user_content and privatekey is None:\n            cert = self.user.getCert(self.site.address)\n            extend[\"cert_auth_type\"] = cert[\"auth_type\"]\n            extend[\"cert_user_id\"] = self.user.getCertUserId(site.address)\n            extend[\"cert_sign\"] = cert[\"cert_sign\"]\n            self.log.debug(\"Extending content.json with cert %s\" % extend[\"cert_user_id\"])\n\n        if not self.hasFilePermission(inner_path):\n            self.log.error(\"SiteSign error: you don't own this site & site owner doesn't allow you to do so.\")\n            return self.response(to, {\"error\": \"Forbidden, you can only modify your own sites\"})\n\n        if privatekey == \"stored\":  # Get privatekey from sites.json\n            privatekey = self.user.getSiteData(self.site.address).get(\"privatekey\")\n            if not privatekey:","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/HelloZeroNet/ZeroNet/blob/454c0b2e7e000fda7000cba49027541fbf327b96/src/Ui/UiWebsocket.py#L397-L433","documentation":"actionSiteSign needs to locate the content.json that governs the file being signed. When inner_path is not itself a content.json, it asks content_manager.getFileInfo(inner_path); if that returns None the file does not belong to any known content.json rule, so signing is impossible and this Exception is raised.","triggerScenarios":"Calling siteSign (via the UiWebsocket API) with an inner_path that (a) does not exist in the site's content.json rules, (b) is misspelled, or (c) is excluded from all content.json includes patterns, and the path doesn't end with 'content.json'.","commonSituations":"Signing a newly created file before adding it to the content.json 'files' include pattern; typo in inner_path; trying to sign files in a directory not covered by any include; permission/ownership mismatches in user content.","solutions":["Verify the file path exists on disk and is covered by an include pattern (e.g. 'files/**') in the site's content.json","Call content_manager.getFileInfo(inner_path) yourself first to confirm the file is tracked before signing","Update content.json include patterns to cover the file, re-sign the content.json, then sign the file","Check inner_path spelling, leading slash, and that you're passing a relative inner path (no site address prefix)"],"exampleFix":"// before\nsite_info = ws.api.siteSign(inner_path='data/newfile.json')\n// after\nif not ws.api.siteInfo()['content_manager'].getFileInfo('data/newfile.json'):\n    raise ValueError('add data/newfile.json to content.json include patterns first')\nsite_info = ws.api.siteSign(inner_path='data/newfile.json')","handlingStrategy":"validation","validationCode":"file_info = site.content_manager.getFileInfo(inner_path)\nif not inner_path.endswith('content.json') and not file_info:\n    raise ValueError(f'{inner_path} is not covered by any content.json rule')","typeGuard":null,"tryCatchPattern":"try:\n    ws.api.siteSign(inner_path=inner_path)\nexcept Exception as e:\n    if str(e).startswith('Invalid content.json file'):\n        update_content_json_includes(inner_path)  # add include pattern, re-sign\n    else:\n        raise","preventionTips":["Check getFileInfo(inner_path) returns a dict before signing","Ensure every file you ship is matched by an include pattern in content.json","Pass relative inner paths without site address prefix","After adding new files, re-sign the governing content.json first"],"tags":["content-json","signing","zeronet"],"backgroundTag":"invalid-content-json","analyzedSha":"454c0b2e7e000fda7000cba49027541fbf327b96","analyzedAt":"2026-09-02T19:46:57.278Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}