{"record":{"id":"989e5c4684bf9b9d","repo":"HelloZeroNet/ZeroNet","slug":"invalid-cert","errorCode":null,"errorMessage":"Invalid cert!","messagePattern":"Invalid cert!","errorType":"validation","errorClass":"VerifyError","httpStatus":null,"severity":"error","filePath":"src/Content/ContentManager.py","lineNumber":989,"sourceCode":"                modified = new_content[\"modified\"]\n                if config.fix_float_decimals and type(modified) is float and not str(modified).endswith(\".0\"):\n                    modified_fixed = \"{:.6f}\".format(modified).strip(\"0.\")\n                    sign_content = sign_content.replace(\n                        '\"modified\": %s' % repr(modified),\n                        '\"modified\": %s' % modified_fixed\n                    )\n\n                if signs:  # New style signing\n                    valid_signers = self.getValidSigners(inner_path, new_content)\n                    signs_required = self.getSignsRequired(inner_path, new_content)\n\n                    if inner_path == \"content.json\" and len(valid_signers) > 1:  # Check signers_sign on root content.json\n                        signers_data = \"%s:%s\" % (signs_required, \",\".join(valid_signers))\n                        if not CryptBitcoin.verify(signers_data, self.site.address, new_content[\"signers_sign\"]):\n                            raise VerifyError(\"Invalid signers_sign!\")\n\n                    if inner_path != \"content.json\" and not self.verifyCert(inner_path, new_content):  # Check if cert valid\n                        raise VerifyError(\"Invalid cert!\")\n\n                    valid_signs = 0\n                    for address in valid_signers:\n                        if address in signs:\n                            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","sourceCodeStart":971,"sourceCodeEnd":1007,"githubUrl":"https://github.com/HelloZeroNet/ZeroNet/blob/454c0b2e7e000fda7000cba49027541fbf327b96/src/Content/ContentManager.py#L971-L1007","documentation":"verifyFile raises VerifyError('Invalid cert!') when a non-root inner_path's content.json fails self.verifyCert(inner_path, new_content). For user content (e.g. data users publish under users/<address>/content.json), the content must carry a valid certificate (cert_user_id, cert_sign, etc.) issued by a recognized cert provider and whose issuer matches a valid signer of the site. Failure means the certificate signature, issuer, or cert_user_id is missing/invalid or the issuer is not an authorized site signer.","triggerScenarios":"verifyFile with inner_path != 'content.json' calls verifyCert; it returns False because cert_sign does not verify against the cert issuer's address, cert_user_id is malformed, the issuer address is not in the site's valid signers, or the cert fields were edited after signing.","commonSituations":"User trying to post to a ZeroMe/Forum-style site without a valid identity cert; a revoked/expired cert from the identity provider; hand-copied content.json with a cert for a different username/address; site changed its accepted cert issuers after the user signed.","solutions":["Re-obtain a valid certificate from the identity provider (e.g. via ZeroID/ZeroMe) and include the fresh cert fields (cert_user_id, cert_sign) in your content.json before signing","Verify cert_user_id format is 'username@domain' and the issuer domain is accepted by the site's rules","Make sure you sign your content.json with the key matching the certified address","If you own the site, check that the cert issuer's address is listed among the site's valid signers"],"exampleFix":"// before: content.json missing/edited cert\n{\"cert_user_id\": \"bob@zeroid.bit\", \"files\": {...}}  // no cert_sign or wrong cert\n// after: valid cert attached then signed\n{\"cert_user_id\": \"bob@zeroid.bit\", \"cert_sign\": \"<valid_sig_from_issuer>\", \"files\": {...}}","handlingStrategy":"validation","validationCode":"content = json.load(open('users/<addr>/content.json'))\nrequired = ('cert_user_id', 'cert_sign')\nif not all(k in content for k in required):\n    raise ValueError('missing cert fields')\nuser, issuer_domain = content['cert_user_id'].split('@')\n# confirm issuer is an accepted cert provider of the site\nvalid_issuers = content_manager.getValidSigners('content.json', root_content)\nassert content['cert_user_id'] in known_valid_certs, 'obtain fresh cert from provider'","typeGuard":"def has_cert(content):\n    return bool(content.get('cert_user_id')) and bool(content.get('cert_sign'))","tryCatchPattern":"from Content.ContentManager import VerifyError\ntry:\n    site.content_manager.isModified(inner_path, file)\nexcept VerifyError as e:\n    if str(e) == 'Invalid cert!':\n        obtain_new_cert()  # re-auth with identity provider, re-sign content\n    else:\n        raise","preventionTips":["Always fetch a fresh cert before signing user content","Never hand-edit cert_user_id or cert_sign after signing","Confirm the cert issuer domain is still accepted by the site"],"tags":["zeronet","certificate","content-verification","identity"],"backgroundTag":"invalid-certificate","analyzedSha":"454c0b2e7e000fda7000cba49027541fbf327b96","analyzedAt":"2026-09-02T19:46:57.278Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}