{"id":"0ed909bfab5e8c8f","repo":"psf/requests","slug":"auth-hooks-must-be-callable","errorCode":null,"errorMessage":"Auth hooks must be callable.","messagePattern":"Auth hooks must be callable\\.","errorType":"validation","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"src/requests/auth.py","lineNumber":82,"sourceCode":"\n    if isinstance(username, str):\n        username = username.encode(\"latin1\")\n\n    if isinstance(password, str):\n        password = password.encode(\"latin1\")\n\n    authstr = \"Basic \" + to_native_string(\n        b64encode(b\":\".join((username, password))).strip()\n    )\n\n    return authstr\n\n\nclass AuthBase:\n    \"\"\"Base class that all auth implementations derive from\"\"\"\n\n    def __call__(self, r: PreparedRequest) -> PreparedRequest:\n        raise NotImplementedError(\"Auth hooks must be callable.\")\n\n\nclass HTTPBasicAuth(AuthBase):\n    \"\"\"Attaches HTTP Basic Authentication to the given Request object.\"\"\"\n\n    username: bytes | str\n    password: bytes | str\n\n    @overload\n    def __init__(self, username: str, password: str) -> None: ...\n    @overload\n    def __init__(self, username: bytes, password: bytes) -> None: ...\n\n    def __init__(self, username: bytes | str, password: bytes | str) -> None:\n        self.username = username\n        self.password = password\n\n    def __eq__(self, other: object) -> bool:","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/psf/requests/blob/414f0513c33883adf6f2b46901d4f0b38a455851/src/requests/auth.py#L64-L100","documentation":"A NotImplementedError raised by AuthBase.__call__ in src/requests/auth.py. AuthBase is the abstract base for all Requests auth handlers; subclasses must override __call__(self, r) to modify and return the PreparedRequest (typically by setting r.headers['Authorization']). If the base implementation runs, either a subclass forgot the override or a non-callable was passed as auth.","triggerScenarios":"Passing auth=MyAuth() where MyAuth subclasses AuthBase without defining __call__ (or defines it with the wrong name/signature so the base method is hit); instantiating AuthBase directly as an auth handler in requests.get(url, auth=AuthBase()).","commonSituations":"Writing custom token/HMAC/signing auth classes and misspelling __call__ (e.g. defining call or authenticate instead); copying an example that only defines __init__; subclassing AuthBase for typing purposes and never implementing the hook.","solutions":["Implement __call__(self, r) in your AuthBase subclass, mutate r (usually r.headers), and return r.","For simple bearer tokens, skip the class entirely and pass headers={'Authorization': f'Bearer {token}'} or use a (user, pass) tuple for basic auth.","Verify the method is named exactly __call__ with the (self, r) signature and that it returns the request."],"exampleFix":"# before\nclass TokenAuth(requests.auth.AuthBase):\n    def __init__(self, token):\n        self.token = token\n    def apply(self, r):  # wrong method name\n        r.headers['Authorization'] = f'Bearer {self.token}'\n        return r\n\n# after\nclass TokenAuth(requests.auth.AuthBase):\n    def __init__(self, token):\n        self.token = token\n    def __call__(self, r):\n        r.headers['Authorization'] = f'Bearer {self.token}'\n        return r","handlingStrategy":"type-guard","validationCode":"assert callable(auth) or isinstance(auth, tuple), 'auth must be callable (AuthBase) or a (user, pass) tuple'","typeGuard":"from requests.auth import AuthBase\n\ndef is_valid_auth(auth):\n    return auth is None or callable(auth) or (isinstance(auth, tuple) and len(auth) == 2)","tryCatchPattern":"try:\n    resp = session.get(url, auth=my_auth)\nexcept ValueError as e:\n    if 'callable' in str(e):\n        raise TypeError('auth must implement __call__; subclass requests.auth.AuthBase') from e\n    raise","preventionTips":["Custom auth must subclass requests.auth.AuthBase and implement __call__(self, r) returning r — pass an instance, e.g. auth=MyAuth(), not the class or a plain object","For basic auth just pass a ('user', 'pass') tuple; requests converts it internally","Verify callable(auth) in your own config-loading code before wiring it into a session","Don't pass strings or dicts as auth — they aren't callable and fail when hooks are registered"],"tags":["auth","authbase","not-implemented","custom-auth"],"analyzedSha":"414f0513c33883adf6f2b46901d4f0b38a455851","analyzedAt":"2026-07-31T19:24:57.696Z","schemaVersion":2}