{"record":{"id":"be213823909a7df7","repo":"yt-dlp/yt-dlp","slug":"error-msg-login-hint","errorCode":null,"errorMessage":"{error_msg}{login_hint}","messagePattern":"\\{error_msg\\}\\{login_hint\\}","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"yt_dlp/extractor/weverse.py","lineNumber":159,"sourceCode":"\n    def _get_authorization_header(self):\n        if not self._is_logged_in:\n            return {}\n        if self._token_is_expired(self._ACCESS_TOKEN_KEY):\n            self._refresh_access_token()\n        return {'Authorization': f'Bearer {self._oauth_tokens[self._ACCESS_TOKEN_KEY]}'}\n\n    def _report_login_error(self, error_id):\n        error_msg = self._LOGIN_ERRORS_MAP[error_id]\n        username = self._get_login_info()[0]\n\n        if error_id == 'invalid_username':\n            error_msg = error_msg.format(username)\n            username = f'{self._OAUTH_PREFIX}+{username}'\n        elif not username:\n            username = f'{self._OAUTH_PREFIX}+USERNAME'\n\n        raise ExtractorError(join_nonempty(\n            error_msg, self._LOGIN_HINT_TMPL.format(self._OAUTH_PREFIX, self._REFRESH_TOKEN_KEY, username),\n            'Or else you can u', self._login_hint(method='session_cookies')[1:], delim=''), expected=True)\n\n    def _perform_login(self, username, password):\n        if self._is_logged_in:\n            return\n\n        if username.partition('+')[0] != self._OAUTH_PREFIX:\n            self._report_login_error('invalid_username')\n\n        self._oauth_tokens.update(self.cache.load(self._NETRC_MACHINE, self._oauth_cache_key, default={}))\n        if self._is_logged_in and self._access_token_is_valid():\n            return\n\n        rt_key = self._REFRESH_TOKEN_KEY\n        if not self._oauth_tokens.get(rt_key) or self._token_is_expired(rt_key):\n            if try_call(lambda: jwt_decode_hs256(password)['scope']) != 'refresh':\n                self._report_login_error('invalid_password')","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/yt-dlp/yt-dlp/blob/81ecd58b1394793e6da9998cc19fdb45657f1685/yt_dlp/extractor/weverse.py#L141-L177","documentation":"Weverse does not accept email/password in yt-dlp. Login works via OAuth tokens: the username must start with the literal prefix 'oauth' (e.g. oauth+LABEL), and the password must be the refresh token copied from the browser cookie. _report_login_error wraps the mapped error message with a hint that spells out the exact --username/--password values or the session-cookie alternative.","triggerScenarios":"Running with --username that does not start with 'oauth+' (e.g. an email address), passing an access token instead of the refresh token as the password, an expired cached refresh token, or hitting members-only content with no login at all - each maps to an id in _LOGIN_ERRORS_MAP and this combined message-plus-hint.","commonSituations":"Trying email+password like a normal site; copying the wrong cookie value; refresh tokens expiring after web re-login; stale cached tokens on disk.","solutions":["Follow the hint embedded in the error text: --username 'oauth+ANY_LABEL' --password 'REFRESH_TOKEN' where REFRESH_TOKEN is the value of the cookie named in the message from a logged-in browser","Run 'yt-dlp --rm-cache-dir' to drop stale cached Weverse tokens, then log in again with a fresh refresh token","Alternatively export session cookies from a logged-in browser with --cookies-from-browser","Update yt-dlp - the token scheme and hint text have changed across releases"],"exampleFix":"# before: email/password is not a valid Weverse login for yt-dlp\nyt-dlp --username fan@mail.com --password hunter2 'https://weverse.io/artist/live/1-123'\n# after: oauth-prefixed username + refresh token cookie value\nyt-dlp --username 'oauth+fan@mail.com' --password 'REFRESH_TOKEN_FROM_BROWSER_COOKIE' 'https://weverse.io/artist/live/1-123'","handlingStrategy":"try-catch","validationCode":"# Weverse login contract: username must start with 'oauth+' and the\n# password must be the refresh token cookie value, not the account password.\nif not username.startswith('oauth+'):\n    raise ValueError(\"Weverse username must be 'oauth+LABEL', not an email\")\nif password == account_password:\n    raise ValueError('Weverse password must be the refresh token cookie value from the browser')","typeGuard":"def is_weverse_login_hint(exc: Exception) -> bool:\n    return isinstance(exc, ExtractorError) and (\n        'not valid login username' in str(exc)\n        or 'valid refresh token' in str(exc)\n        or 'logged-in users' in str(exc)\n        or 'refresh token' in str(exc))","tryCatchPattern":"try:\n    with YoutubeDL({'username': 'oauth+main', 'password': refresh_token}) as ydl:\n        ydl.download([url])\nexcept DownloadError as e:\n    if 'refresh token' in str(e) or 'login' in str(e):\n        refresh_token = fetch_fresh_refresh_token_cookie()  # from the logged-in browser\n        subprocess.run(['yt-dlp', '--rm-cache-dir'])\n        retry_with(refresh_token)\n    else:\n        raise","preventionTips":["Always use the 'oauth+' username prefix and the refresh token cookie as the password","Copy the cookie value named in the error hint, not the access token","Clear the yt-dlp cache after re-logging in on the web so stale tokens are dropped","Automate token refresh by exporting fresh cookies periodically for long-running jobs"],"tags":["weverse","login","oauth","refresh-token","username-format"],"backgroundTag":"oauth-token-auth-required","analyzedSha":"81ecd58b1394793e6da9998cc19fdb45657f1685","analyzedAt":"2026-08-22T12:21:25.439Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}