Skip to content

fix(route/twitter): defensive fallback for missing profile_image_url (avoid /twitter/user/* 503)#22137

Open
Dinglingyun2022 wants to merge 1 commit into
DIYgod:masterfrom
Dinglingyun2022:fix/twitter-user-undefined-profile-image-url
Open

fix(route/twitter): defensive fallback for missing profile_image_url (avoid /twitter/user/* 503)#22137
Dinglingyun2022 wants to merge 1 commit into
DIYgod:masterfrom
Dinglingyun2022:fix/twitter-user-undefined-profile-image-url

Conversation

@Dinglingyun2022
Copy link
Copy Markdown

Involved Issue / 该 PR 相关 Issue

Defensive guard related to #22136 (does not fix the root cause; see "Scope" below).

Example for the Proposed Route(s) / 路由地址示例

/twitter/user/:id

New RSS Route Checklist / 新 RSS 路由检查表

  • New Route / 新的路由
  • Anti-bot or rate limit / 反爬/频率限制
    • If yes, do your code reflect this sign? / 如果有, 是否有对应的措施?
  • Date and time / 日期和时间
    • Parsed / 可以解析
    • Provided as ISO 8601 / UTC / 以 ISO 8601 / UTC 提供
  • Author in namespace.ts is included / namespace.ts 中含有 作者
  • Bug fix / 修复 bug

Note / 说明

Summary

lib/routes/twitter/user.ts:91 calls profileImageUrl.replace(...) without optional chaining. When api.getUser(id) returns user info whose profile_image_url / profile_image_url_https fields are missing (observed when X changes the API contract — see #22136), profileImageUrl resolves to undefined, and the unguarded .replace() call throws TypeError: Cannot read properties of undefined (reading 'replace'), making the entire /twitter/user/* route return HTTP 503.

Diff

-        image: profileImageUrl.replace(/_normal.jpg$/, '.jpg'),
+        image: profileImageUrl?.replace(/_normal.jpg$/, '.jpg') ?? 'https://abs.twimg.com/sticky/default_profile_images/default_profile_400x400.png',

One-line change: add optional chaining and fall back to X's official default profile image when the field is missing.

Scope

Why this is still valuable even after #22136 root cause lands

This is a generic defensive guard against future X API contract changes. X has historically renamed / removed fields on UserByScreenName multiple times. With this guard in place, future similar regressions degrade gracefully (default avatar) instead of crashing the entire route with a confusing TypeError.

Symptom reference (from #22136)

info: <-- GET /twitter/user/dscassoc
info: twitter gql-id-resolver: fetching fresh query IDs from Twitter JS bundles
error: Error in /twitter/user/dscassoc: TypeError: Cannot read properties of undefined (reading 'replace')
info: --> GET /twitter/user/dscassoc 503 14s

When api.getUser() returns user info without profile_image_url (observed
when X changes API contract, see DIYgod#22136), the unguarded .replace() call
on user.ts:91 throws TypeError and the entire /twitter/user/* route
returns 503.

Add optional chaining + fallback to X's default profile image, allowing
the route to degrade gracefully instead of crashing the whole feed.

This is a defensive guard only; the root cause (X API contract change)
is tracked in DIYgod#22136 and requires updates to gql-id-resolver / query
IDs / GraphQL features.
@github-actions github-actions Bot added the route label May 30, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Please use actual values in routes section instead of path parameters.
请在 routes 部分使用实际值而不是路径参数。

@github-actions github-actions Bot added the auto: route no found Automated test failed due to route can not be found in PR description body label May 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto: route no found Automated test failed due to route can not be found in PR description body route

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant