DIYgod/RSSHub · error · ConfigNotFoundError

This user is an R18 creator, PIXIV_REFRESHTOKEN is required.

Error message

This user is an R18 creator, PIXIV_REFRESHTOKEN is required.
pixiv RSS is disabled due to the lack of relevant config.
該用戶爲 R18 創作者,需要 PIXIV_REFRESHTOKEN。

What it means

Thrown by getNSFWUserNovels (pixiv R18 user-novels path) when config.pixiv or config.pixiv.refreshToken is falsy. Identical in cause to the series-NSFW config guard: R18 novel content requires an authenticated pixiv account, so the route aborts before calling the app API. It is a ConfigNotFoundError aimed at the operator, not the requester.

Source

Thrown at lib/routes/pixiv/novel-api/user-novels/nsfw.ts:31

import { convertPixivProtocolExtended } from '../content/utils';
import type { NovelList, NSFWNovelsResponse } from './types';

function getNovels(user_id: string, token: string): Promise<NSFWNovelsResponse> {
    return got('https://app-api.pixiv.net/v1/user/novels', {
        headers: {
            ...maskHeader,
            Authorization: 'Bearer ' + token,
        },
        searchParams: queryString.stringify({
            user_id,
            filter: 'for_ios',
        }),
    });
}

export async function getNSFWUserNovels(id: string, fullContent: boolean = false, limit: number = 100): Promise<NovelList> {
    if (!config.pixiv || !config.pixiv.refreshToken) {
        throw new ConfigNotFoundError('This user is an R18 creator, PIXIV_REFRESHTOKEN is required.\npixiv RSS is disabled due to the lack of relevant config.\n該用戶爲 R18 創作者,需要 PIXIV_REFRESHTOKEN。');
    }

    const token = await getToken();
    if (!token) {
        throw new ConfigNotFoundError('pixiv not login');
    }

    const response = await getNovels(id, token);
    const novels = limit ? response.data.novels.slice(0, limit) : response.data.novels;

    if (novels.length === 0) {
        throw new InvalidParameterError(`${id} is not a valid user ID, or the user has no novels.\n${id} 不是有效的用戶 ID,或者該用戶沒有小說作品。`);
    }

    const username = novels[0].user.name;

    const items = await Promise.all(
        novels.map(async (novel) => {

View on GitHub (pinned to bed535e087)

Solutions

  1. Configure PIXIV_REFRESHTOKEN in the environment and restart RSSHub.
  2. Verify config.pixiv.refreshToken is truthy at runtime via a debug check.
  3. If R18 access is not needed, ensure the route resolves through the SFW user-novels path instead.
  4. Check that the env var name exactly matches PIXIV_REFRESHTOKEN (no extra spaces, correct casing).

Example fix

// before: PIXIV_REFRESHTOKEN is unset
// after (in .env):
PIXIV_REFRESHTOKEN=your_refresh_token_here
Defensive patterns

Strategy: validation

Validate before calling

import { config } from '@/config';
function canFetchNSFWUserNovels(): boolean {
  return Boolean(config.pixiv && config.pixiv.refreshToken);
}
if (!canFetchNSFWUserNovels()) {
  // refuse R18 user-novels request with a clear config notice
}

Type guard

const hasPixivAuth = (c: typeof config): c is typeof config & { pixiv: { refreshToken: string } } =>
  Boolean(c.pixiv && typeof c.pixiv.refreshToken === 'string' && c.pixiv.refreshToken.length > 0);

Try / catch

try {
  return await getNSFWUserNovels(id, fullContent, limit);
} catch (e) {
  if (e instanceof ConfigNotFoundError && /PIXIV_REFRESHTOKEN/.test(e.message)) {
    // surface config guidance; do not retry
  }
  throw e;
}

Prevention

When it happens

Trigger: Hitting the NSFW user-novels branch (the /pixiv/user/novels/:id route when hasPixivAuth() is true is actually the entry, but this inner function is also callable directly) while PIXIV_REFRESHTOKEN is unset or empty.

Common situations: Instance deployed without pixiv credentials; env var dropped during a redeploy; misconfigured secrets manager; the novels handler routing into the NSFW helper without the token actually present.

Related errors


AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12). Data as JSON: /api/errors/1d599979f7bcfd59. Report an issue: GitHub.