{"record":{"id":"1d599979f7bcfd59","repo":"DIYgod/RSSHub","slug":"this-user-is-an-r18-creator-pixiv-refreshtoken-is-1d5999","errorCode":null,"errorMessage":"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。","messagePattern":"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。","errorType":"exception","errorClass":"ConfigNotFoundError","httpStatus":null,"severity":"error","filePath":"lib/routes/pixiv/novel-api/user-novels/nsfw.ts","lineNumber":31,"sourceCode":"import { convertPixivProtocolExtended } from '../content/utils';\nimport type { NovelList, NSFWNovelsResponse } from './types';\n\nfunction getNovels(user_id: string, token: string): Promise<NSFWNovelsResponse> {\n    return got('https://app-api.pixiv.net/v1/user/novels', {\n        headers: {\n            ...maskHeader,\n            Authorization: 'Bearer ' + token,\n        },\n        searchParams: queryString.stringify({\n            user_id,\n            filter: 'for_ios',\n        }),\n    });\n}\n\nexport async function getNSFWUserNovels(id: string, fullContent: boolean = false, limit: number = 100): Promise<NovelList> {\n    if (!config.pixiv || !config.pixiv.refreshToken) {\n        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。');\n    }\n\n    const token = await getToken();\n    if (!token) {\n        throw new ConfigNotFoundError('pixiv not login');\n    }\n\n    const response = await getNovels(id, token);\n    const novels = limit ? response.data.novels.slice(0, limit) : response.data.novels;\n\n    if (novels.length === 0) {\n        throw new InvalidParameterError(`${id} is not a valid user ID, or the user has no novels.\\n${id} 不是有效的用戶 ID，或者該用戶沒有小說作品。`);\n    }\n\n    const username = novels[0].user.name;\n\n    const items = await Promise.all(\n        novels.map(async (novel) => {","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/pixiv/novel-api/user-novels/nsfw.ts#L13-L49","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Configure PIXIV_REFRESHTOKEN in the environment and restart RSSHub.","Verify config.pixiv.refreshToken is truthy at runtime via a debug check.","If R18 access is not needed, ensure the route resolves through the SFW user-novels path instead.","Check that the env var name exactly matches PIXIV_REFRESHTOKEN (no extra spaces, correct casing)."],"exampleFix":"// before: PIXIV_REFRESHTOKEN is unset\n// after (in .env):\nPIXIV_REFRESHTOKEN=your_refresh_token_here","handlingStrategy":"validation","validationCode":"import { config } from '@/config';\nfunction canFetchNSFWUserNovels(): boolean {\n  return Boolean(config.pixiv && config.pixiv.refreshToken);\n}\nif (!canFetchNSFWUserNovels()) {\n  // refuse R18 user-novels request with a clear config notice\n}","typeGuard":"const hasPixivAuth = (c: typeof config): c is typeof config & { pixiv: { refreshToken: string } } =>\n  Boolean(c.pixiv && typeof c.pixiv.refreshToken === 'string' && c.pixiv.refreshToken.length > 0);","tryCatchPattern":"try {\n  return await getNSFWUserNovels(id, fullContent, limit);\n} catch (e) {\n  if (e instanceof ConfigNotFoundError && /PIXIV_REFRESHTOKEN/.test(e.message)) {\n    // surface config guidance; do not retry\n  }\n  throw e;\n}","preventionTips":["Gate the NSFW user-novels call behind a shared hasPixivAuth() helper.","Run env-var presence checks at startup for routes that advertise optional pixiv config.","Keep the SFW path as the unauthenticated default."],"tags":["pixiv","config","nsfw","authentication","novel"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}