{"id":"dc8fa2d5792c9317","repo":"redis/redis-py","slug":"unexpected-token-schema-following-fields-are-miss","errorCode":null,"errorMessage":"Unexpected token schema. Following fields are missing: {missing_fields}","messagePattern":"Unexpected token schema\\. Following fields are missing: (.+?)","errorType":"exception","errorClass":"InvalidTokenSchemaErr","httpStatus":null,"severity":"error","filePath":"redis/auth/token.py","lineNumber":130,"sourceCode":"        )\n\n    def try_get(self, key: str) -> str:\n        return self._decoded.get(key)\n\n    def get_value(self) -> str:\n        return self._value\n\n    def get_expires_at_ms(self) -> float:\n        return float(self._decoded[\"exp\"] * 1000)\n\n    def get_received_at_ms(self) -> float:\n        return datetime.now(timezone.utc).timestamp() * 1000\n\n    def _validate_token(self):\n        actual_fields = {x for x in self._decoded.keys()}\n\n        if len(self.REQUIRED_FIELDS - actual_fields) != 0:\n            raise InvalidTokenSchemaErr(self.REQUIRED_FIELDS - actual_fields)\n","sourceCodeStart":112,"sourceCodeEnd":131,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/auth/token.py#L112-L131","documentation":"Raised as InvalidTokenSchemaErr by JWToken._validate_token (redis/auth/token.py:130) when the decoded JWT is missing one or more REQUIRED_FIELDS (currently {\"exp\"}). The message lists exactly which fields are absent. The token may be valid JWT structurally but lacks the claims this library requires.","triggerScenarios":"Passing a JWT to JWToken that has no `exp` claim; a token issued by an IdP that uses a custom expiry claim instead of standard `exp`; a malformed or truncated token that decodes to a near-empty payload.","commonSituations":"Custom/proprietary JWT format from a non-standard identity provider; test fixtures with hand-built tokens missing exp; token corruption in transit.","solutions":["Ensure the token includes the standard `exp` (Unix timestamp) claim.","If your IdP uses a different expiry claim, request a standards-compliant token or pre-process it to add exp.","For tokens that genuinely never expire, set exp to a far-future value or use SimpleToken with expires_at_ms=-1."],"exampleFix":"# before\ntoken_payload = {'sub': 'user1'}  # no exp -> InvalidTokenSchemaErr\n# after\nimport time\ntoken_payload = {'sub': 'user1', 'exp': int(time.time()) + 3600}","handlingStrategy":"validation","validationCode":"import time\nrequired = {'exp'}\npayload = decode_unverified(raw_jwt)\nmissing = required - set(payload)\nif missing:\n    raise ValueError(f'token missing fields: {missing}')","typeGuard":"def has_required_claims(decoded: dict, required={'exp'}) -> bool:\n    return required.issubset(decoded.keys())","tryCatchPattern":"from redis.auth.err import InvalidTokenSchemaErr\ntry:\n    t = JWToken(raw_jwt)\nexcept InvalidTokenSchemaErr as e:\n    logger.error('rejecting malformed token: %s', e)\n    raise","preventionTips":["Require the IdP to issue standards-compliant JWTs with exp.","Validate payload claims before constructing JWToken."],"tags":["auth","jwt","validation"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}