{"record":{"id":"251d7be11e1e1002","repo":"ytdl-org/youtube-dl","slug":"unable-to-login-s-251d7b","errorCode":null,"errorMessage":"Unable to login: %s","messagePattern":"Unable to login: (.+?)","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/teachable.py","lineNumber":98,"sourceCode":"            data=urlencode_postdata(login_form),\n            headers={\n                'Content-Type': 'application/x-www-form-urlencoded',\n                'Referer': login_url,\n            })\n\n        if '>I accept the new Privacy Policy<' in response:\n            raise ExtractorError(\n                'Unable to login: %s asks you to accept new Privacy Policy. '\n                'Go to https://%s/ and accept.' % (site, site), expected=True)\n\n        # Successful login\n        if is_logged(response):\n            self._logged_in = True\n            return\n\n        message = get_element_by_class('alert', response)\n        if message is not None:\n            raise ExtractorError(\n                'Unable to login: %s' % clean_html(message), expected=True)\n\n        raise ExtractorError('Unable to log in')\n\n\nclass TeachableIE(TeachableBaseIE):\n    _VALID_URL = r'''(?x)\n                    (?:\n                        %shttps?://(?P<site_t>[^/]+)|\n                        https?://(?:www\\.)?(?P<site>%s)\n                    )\n                    /courses/[^/]+/lectures/(?P<id>\\d+)\n                    ''' % TeachableBaseIE._VALID_URL_SUB_TUPLE\n\n    _TESTS = [{\n        'url': 'https://gns3.teachable.com/courses/gns3-certified-associate/lectures/6842364',\n        'info_dict': {\n            'id': 'untlgzk1v7',","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/teachable.py#L80-L116","documentation":"Raised by TeachableBaseIE._login when the login POST went through (no privacy-policy marker) and is_logged(response) is false, but the response contains an element with class 'alert'. The alert's cleaned text (typically 'Invalid email or password' or 'account locked') is surfaced as 'Unable to login: <alert text>' with expected=True.","triggerScenarios":"Logging in with wrong username/password or a locked/disabled account on any Teachable-based site: the school returns its HTML page with an alert div instead of a logged-in session.","commonSituations":"Wrong or stale password (school reset it); expired/deleted course accounts; password managers auto-filling outdated netrc entries; MFA-enabled accounts that cannot complete the CLI flow.","solutions":["Read the alert text in the message — it is the school's own login failure reason; correct the credentials in .netrc or --username/--password accordingly.","Confirm the login works in a browser on the same site; if the browser also fails, fix the account first.","Verify you are using credentials for the right school subdomain (Teachable accounts are per-site in this extractor).","If MFA is required, create a session in a browser and reuse cookies rather than CLI login."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# Verify credentials in a browser first; programmatic equivalent is just\n# attempting login and inspecting the expected alert error","typeGuard":null,"tryCatchPattern":"try:\n    ydl.extract_info(url)\nexcept ExtractorError as e:\n    if e.expected and 'Unable to login' in str(e):\n        log.error('Teachable login refused: %s', str(e))  # alert text included\n        notify_credentials_issue(site)\n    else:\n        raise","preventionTips":["Test Teachable school credentials in a browser before CLI use.","Keep .netrc entries per-school and current.","Watch for MFA on school accounts — use --cookies instead when enabled."],"tags":["login","credentials","expected-error","teachable"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}