psf/requests · error · TypeError

max-age: {morsel['max-age']} must be integer

Error message

max-age: {morsel['max-age']} must be integer

What it means

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.

Source

Thrown at src/requests/cookies.py:539

    result.update(kwargs)
    result["port_specified"] = bool(result["port"])
    result["domain_specified"] = bool(result["domain"])
    result["domain_initial_dot"] = result["domain"].startswith(".")
    result["path_specified"] = bool(result["path"])

    return cookielib.Cookie(**result)


def morsel_to_cookie(morsel: Morsel[Any]) -> Cookie:
    """Convert a Morsel object into a Cookie containing the one k/v pair."""

    expires: int | None = None
    if morsel["max-age"]:
        try:
            expires = int(time.time() + int(morsel["max-age"]))
        except ValueError:
            raise TypeError(f"max-age: {morsel['max-age']} must be integer")
    elif morsel["expires"]:
        time_template = "%a, %d-%b-%Y %H:%M:%S GMT"
        expires = calendar.timegm(time.strptime(morsel["expires"], time_template))
    return create_cookie(
        comment=morsel["comment"],
        comment_url=bool(morsel["comment"]),
        discard=False,
        domain=morsel["domain"],
        expires=expires,
        name=morsel.key,
        path=morsel["path"],
        port=None,
        rest={"HttpOnly": morsel["httponly"]},
        rfc2109=False,
        secure=bool(morsel["secure"]),
        value=morsel.value,
        version=morsel["version"] or 0,
    )

View on GitHub ↗ (pinned to 414f0513c3)

Solutions

  1. Sanitize the Morsel before conversion: coerce morsel['max-age'] = str(int(float(raw))) or delete the attribute and rely on 'expires'.
  2. Fix the producing side (server/framework) to emit an integer Max-Age per RFC 6265.
  3. If the max-age is meaningless, remove it and set morsel['expires'] to an RFC 1123 date string instead.

Example fix

# before
morsel['max-age'] = '3600.5'
cookie = morsel_to_cookie(morsel)  # TypeError

# after
morsel['max-age'] = str(int(float(morsel['max-age'])))
cookie = morsel_to_cookie(morsel)
Defensive patterns

Strategy: validation

Validate before calling

morsel = cookie_obj  # http.cookies.Morsel
if morsel['max-age']:
    try:
        int(morsel['max-age'])
    except ValueError:
        morsel['max-age'] = ''  # strip malformed max-age before conversion

Type guard

def has_valid_max_age(morsel):
    ma = morsel.get('max-age', '')
    if not ma:
        return True
    try:
        int(ma)
        return True
    except (TypeError, ValueError):
        return False

Try / catch

try:
    cookie = requests.cookies.morsel_to_cookie(morsel)
except TypeError:
    morsel['max-age'] = ''
    cookie = requests.cookies.morsel_to_cookie(morsel)

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of psf/requests@414f0513c3 (2026-07-31). Data as JSON: /data/errors/730b2a9f5360bdc4.json. Report an issue: GitHub ↗.