{"record":{"id":"3010a5b3e8945a00","repo":"DIYgod/RSSHub","slug":"no-valid-twitter-token-found","errorCode":null,"errorMessage":"No valid Twitter token found","messagePattern":"No valid Twitter token found","errorType":"exception","errorClass":"ConfigNotFoundError","httpStatus":null,"severity":"error","filePath":"lib/routes/twitter/api/web-api/utils.ts","lineNumber":87,"sourceCode":"    return {\n        token,\n        // username: config.twitter.username?.[index],\n        // password: config.twitter.password?.[index],\n        // authenticationSecret: config.twitter.authenticationSecret?.[index],\n    };\n};\n\nexport const twitterGot = async (\n    url,\n    params,\n    options?: {\n        allowNoAuth?: boolean;\n    }\n) => {\n    const auth = await getAuth(30);\n\n    if (!auth && !options?.allowNoAuth) {\n        throw new ConfigNotFoundError('No valid Twitter token found');\n    }\n\n    const requestUrl = `${url}?${queryString.stringify(params)}`;\n\n    let cookie: string | Record<string, any> | null | undefined = await token2Cookie(auth?.token);\n    // if (!cookie && auth) {\n    //     cookie = await login({\n    //         username: auth.username,\n    //         password: auth.password,\n    //         authenticationSecret: auth.authenticationSecret,\n    //     });\n    // }\n    let dispatchers:\n        | {\n              jar: CookieJar;\n              agent: CookieAgent | ProxyAgent;\n          }\n        | undefined;","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/twitter/api/web-api/utils.ts#L69-L105","documentation":"ConfigNotFoundError thrown by twitterGot when getAuth(30) returns nothing and the caller did not set allowNoAuth. RSSHub requires at least one TWITTER_AUTH_TOKEN (or the deprecated consumer-key config) to call authenticated GraphQL endpoints; with no token and no opt-out, the request cannot be made.","triggerScenarios":"Any authenticated Twitter route (user timeline, lists, media, etc.) is requested while config.twitter.authToken is empty/unset, all tokens are locked (rate-limited) for the next 30 retries, or all tokens were spliced out due to repeated 401/403. allowNoAuth is only true for the unauthenticated user-id-lookup path.","commonSituations":"Fresh RSSHub deploy without TWITTER_AUTH_TOKEN configured; all tokens burned by heavy use and now locked in cache; tokens expired/revoked by Twitter; misconfigured env var name so the array stays empty.","solutions":["Set TWITTER_AUTH_TOKEN (one or more, comma-separated) in the RSSHub environment to a valid x.com browser cookie auth token.","Restart RSSHub so config is re-read.","If tokens are merely locked, wait for the lock TTL (up to 2000s for rate-limit, 3600s for auth-failure) to expire or clear the lockPrefix cache keys.","Verify the token still works by logging into x.com with that cookie."],"exampleFix":"// before: env not set\n// TWITTER_AUTH_TOKEN=\n// after\n// TWITTER_AUTH_TOKEN=abcdef0123...  (cookie 'auth_token' from x.com)","handlingStrategy":"validation","validationCode":"function hasTwitterToken(cfg: any): boolean {\n  return Array.isArray(cfg?.twitter?.authToken) && cfg.twitter.authToken.filter(Boolean).length > 0;\n}\n// call before serving any authenticated twitter route\nif (!hasTwitterToken(config)) { /* return a friendly 'not configured' page */ }","typeGuard":"function isAuthObject(auth: unknown): auth is { token: string } {\n  return typeof auth === 'object' && auth !== null && typeof (auth as any).token === 'string';\n}","tryCatchPattern":"try { await twitterGot(url, params); }\ncatch (e) {\n  if (/No valid Twitter token/.test(String(e))) { /* alert ops: add tokens or wait out locks */ }\n  else throw e;\n}","preventionTips":["Configure multiple TWITTER_AUTH_TOKEN values so one lock does not disable the route.","Alert when the count of non-locked tokens drops below a threshold.","Restart RSSHub after changing env vars to ensure config is reloaded."],"tags":["twitter","config-not-found","auth","configuration","env"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}