DIYgod/RSSHub · error · Error
Failed to fetch followings data
Error message
Failed to fetch followings data
What it means
Thrown at lib/routes/skeb/utils.tsx:136 after fetching `https://skeb.jp/api/users/{username}/followings` with a bearer-token Authorization header. The guard checks that `followings_data` is truthy and an object before calling `.map()` on it. If Skeb's API returns null, an empty string, a 401/403 error body, or a redirect HTML page (ofetch follows redirects and parses whatever comes back), the check fails and the error fires.
Source
Thrown at lib/routes/skeb/utils.tsx:136
export async function getFollowingsItems(username: string, path: 'friend_works' | 'following_works' | 'following_creators'): Promise<DataItem[]> {
const url = `${baseUrl}/api/users/${username.replace('@', '')}/followings`;
const followings_data = await cache.tryGet(
`skeb:followings_data:${username}`,
async () => {
const data = await ofetch(url, {
headers: {
Authorization: `Bearer ${config.skeb.bearerToken}`,
},
});
return data;
},
config.cache.routeExpire,
false
);
if (!followings_data || typeof followings_data !== 'object') {
throw new Error('Failed to fetch followings data');
}
if (path === 'following_creators') {
return followings_data[path].map((item) => processCreator(item)).filter(Boolean) as DataItem[];
}
return followings_data[path].map((item) => processWork(item)).filter(Boolean) as DataItem[];
}
const SkebWorkDescription = ({ imageUrl, body, audioUrl }: { imageUrl?: string; body: string; audioUrl?: string | null }) => (
<>
{imageUrl ? (
<>
<img src={imageUrl} />
<br />
</>
) : null}
{audioUrl ? (
<>View on GitHub (pinned to bed535e087)
Solutions
- Set a fresh SKEB_BEARER_TOKEN in config by logging into skeb.jp and copying the Authorization Bearer value from a real API request in DevTools.
- Verify the username exists by opening `https://skeb.jp/@{username}` in a browser.
- Temporarily log the raw `followings_data` value to see what Skeb actually returned (it may be an auth-error JSON).
- Clear the cache key `skeb:followings_data:{username}` if stale bad data was cached.
Defensive patterns
Strategy: try-catch
Validate before calling
if (!config.skeb.bearerToken) {
throw new ConfigNotFoundError('SKEB_BEARER_TOKEN is not set');
}
const cleanUsername = username.replace('@', '');
if (!cleanUsername) {
throw new InvalidParameterError('username is required');
} Type guard
const isFollowingsResponse = (d: unknown): d is Record<string, unknown[]> =>
!!d && typeof d === 'object' && !Array.isArray(d); Try / catch
try {
const items = await getFollowingsItems(username, path);
} catch (e) {
if (e instanceof Error && e.message === 'Failed to fetch followings data') {
// likely auth or upstream issue; check bearerToken freshness
throw new Error('Skeb followings unavailable — verify SKEB_BEARER_TOKEN and username');
}
throw e;
} Prevention
- Always set SKEB_BEARER_TOKEN from a currently-logged-in skeb.jp browser session.
- Strip the leading '@' from usernames before calling getFollowingsItems.
- Monitor token expiry — Skeb bearer tokens have a limited lifetime and silent failure manifests as this error.
When it happens
Trigger: Calling getFollowingsItems with a username that does not exist; the SKEB_BEARER_TOKEN is expired or revoked so Skeb returns a JSON error object instead of the followings payload; Cloudflare or Skeb rate-limiting returns an interstitial HTML page; the username still has a leading '@' that wasn't stripped correctly (line 119 should strip it but edge cases exist).
Common situations: SKEB_BEARER_TOKEN environment variable not set or left empty; token harvested from a logged-out session; Skeb changed their API response shape; the user passed a screen_name that contains special characters.
Related errors
- Failed to retrieve refresh token from MangaDex API.
- Failed to retrieve access token from MangaDex API.
- Failed to retrieve user settings from MangaDex API.
- Skeb works RSS is disabled due to the lack of <a href="https
- Invalid data received from API
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/d890b8631831b108.
Report an issue: GitHub.