{"id":"730b2a9f5360bdc4","repo":"psf/requests","slug":"max-age-morsel-max-age-must-be-integer","errorCode":null,"errorMessage":"max-age: {morsel['max-age']} must be integer","messagePattern":"max-age: (.+?) must be integer","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/requests/cookies.py","lineNumber":539,"sourceCode":"\n    result.update(kwargs)\n    result[\"port_specified\"] = bool(result[\"port\"])\n    result[\"domain_specified\"] = bool(result[\"domain\"])\n    result[\"domain_initial_dot\"] = result[\"domain\"].startswith(\".\")\n    result[\"path_specified\"] = bool(result[\"path\"])\n\n    return cookielib.Cookie(**result)\n\n\ndef morsel_to_cookie(morsel: Morsel[Any]) -> Cookie:\n    \"\"\"Convert a Morsel object into a Cookie containing the one k/v pair.\"\"\"\n\n    expires: int | None = None\n    if morsel[\"max-age\"]:\n        try:\n            expires = int(time.time() + int(morsel[\"max-age\"]))\n        except ValueError:\n            raise TypeError(f\"max-age: {morsel['max-age']} must be integer\")\n    elif morsel[\"expires\"]:\n        time_template = \"%a, %d-%b-%Y %H:%M:%S GMT\"\n        expires = calendar.timegm(time.strptime(morsel[\"expires\"], time_template))\n    return create_cookie(\n        comment=morsel[\"comment\"],\n        comment_url=bool(morsel[\"comment\"]),\n        discard=False,\n        domain=morsel[\"domain\"],\n        expires=expires,\n        name=morsel.key,\n        path=morsel[\"path\"],\n        port=None,\n        rest={\"HttpOnly\": morsel[\"httponly\"]},\n        rfc2109=False,\n        secure=bool(morsel[\"secure\"]),\n        value=morsel.value,\n        version=morsel[\"version\"] or 0,\n    )","sourceCodeStart":521,"sourceCodeEnd":557,"githubUrl":"https://github.com/psf/requests/blob/414f0513c33883adf6f2b46901d4f0b38a455851/src/requests/cookies.py#L521-L557","documentation":"A TypeError raised by requests.cookies.morsel_to_cookie() in src/requests/cookies.py when converting a http.cookies.Morsel into a cookiejar Cookie. The Max-Age attribute must be convertible with int() so it can be added to time.time() to compute an absolute expiry; a non-integer value raises ValueError internally, which is re-raised as this TypeError.","triggerScenarios":"Calling morsel_to_cookie() (directly, or via requests.utils.add_dict_to_cookiejar/cookiejar_from_dict paths that accept Morsels) on a Morsel whose 'max-age' is set to a non-integer string — e.g. morsel['max-age'] = '3600.5', 'session', or an empty-but-truthy garbage value produced by a noncompliant server or hand-built SimpleCookie.","commonSituations":"Parsing Set-Cookie headers from noncompliant servers that emit fractional or textual Max-Age values; test fixtures constructing Morsels by hand; frameworks that stuff float seconds into max-age.","solutions":["Sanitize the Morsel before conversion: coerce morsel['max-age'] = str(int(float(raw))) or delete the attribute and rely on 'expires'.","Fix the producing side (server/framework) to emit an integer Max-Age per RFC 6265.","If the max-age is meaningless, remove it and set morsel['expires'] to an RFC 1123 date string instead."],"exampleFix":"# before\nmorsel['max-age'] = '3600.5'\ncookie = morsel_to_cookie(morsel)  # TypeError\n\n# after\nmorsel['max-age'] = str(int(float(morsel['max-age'])))\ncookie = morsel_to_cookie(morsel)","handlingStrategy":"validation","validationCode":"morsel = cookie_obj  # http.cookies.Morsel\nif morsel['max-age']:\n    try:\n        int(morsel['max-age'])\n    except ValueError:\n        morsel['max-age'] = ''  # strip malformed max-age before conversion","typeGuard":"def has_valid_max_age(morsel):\n    ma = morsel.get('max-age', '')\n    if not ma:\n        return True\n    try:\n        int(ma)\n        return True\n    except (TypeError, ValueError):\n        return False","tryCatchPattern":"try:\n    cookie = requests.cookies.morsel_to_cookie(morsel)\nexcept TypeError:\n    morsel['max-age'] = ''\n    cookie = requests.cookies.morsel_to_cookie(morsel)","preventionTips":["Validate max-age is an integer string before calling morsel_to_cookie() on Morsels built from untrusted Set-Cookie data","When constructing Morsels yourself, set max-age with str(int(seconds)), never floats like '3600.0'","Sanitize or drop malformed max-age from third-party servers rather than letting a TypeError abort processing"],"tags":["cookies","morsel","max-age","typeerror","parsing"],"analyzedSha":"414f0513c33883adf6f2b46901d4f0b38a455851","analyzedAt":"2026-07-31T19:24:57.696Z","schemaVersion":2}