{"record":{"id":"1597c11b4644c497","repo":"DIYgod/RSSHub","slug":"blog-not-found","errorCode":null,"errorMessage":"Blog Not Found","messagePattern":"Blog Not Found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/lofter/user.ts","lineNumber":53,"sourceCode":"\n    const response = await got({\n        method: 'post',\n        url: 'http://api.lofter.com/v2.0/blogHomePage.api?product=lofter-iphone-10.0.0',\n        body: new URLSearchParams({\n            blogdomain: rootUrl,\n            checkpwd: '1',\n            following: '0',\n            limit: String(limit),\n            method: 'getPostLists',\n            needgetpoststat: '1',\n            offset: '0',\n            postdigestnew: '1',\n            supportposttypes: '1,2,3,4,5,6',\n        }),\n    });\n\n    if (!response.data.response || response.data.response.posts.length === 0) {\n        throw new Error('Blog Not Found');\n    }\n\n    const items = response.data.response.posts.map((item) => ({\n        title: item.post.title || item.post.noticeLinkTitle,\n        link: item.post.blogPageUrl,\n        description:\n            JSON.parse(item.post.photoLinks || '[]')\n                .map((photo) => {\n                    if (photo.raw?.match(/\\/\\/nos\\.netease\\.com\\//)) {\n                        photo.raw = `https://${photo.raw.match(/(imglf\\d)/)[0]}.lf127.net${photo.raw.match(/\\/\\/nos\\.netease\\.com\\/imglf\\d(.*)/)[1]}`;\n                    }\n                    return `<img src=\"${photo.raw || photo.orign}\">`;\n                })\n                .join('') +\n            JSON.parse(item.post.embed ? `[${item.post.embed}]` : '[]')\n                .map((video) => `<video src=\"${video.originUrl}\" poster=\"${video.video_img_url}\" controls=\"controls\"></video>`)\n                .join('') +\n            item.post.content,","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/lofter/user.ts#L35-L71","documentation":"Thrown by the Lofter user handler (lib/routes/lofter/user.ts:53) when `response.data.response` is falsy OR `response.data.response.posts.length === 0`. The blog either does not exist, has no posts, or the Lofter iPhone API returned an error envelope.","triggerScenarios":"Requesting `/lofter/user/<name>/...` for a non-existent or empty blog; the blog is private/banned; the API envelope changed so `posts` moved; the `supportposttypes` filter excludes all of the blog's posts.","commonSituations":"Stale username; blog migrated or deleted; API version mismatch after a Lofter update.","solutions":["Open `https://<name>.lofter.com/` to confirm the blog exists and has posts.","Inspect `response.data` to see whether an error code/message is present under another key.","If the envelope changed, update the guard and the `response.data.response.posts` access path."],"exampleFix":"// before\nif (!response.data.response || response.data.response.posts.length === 0) {\n    throw new Error('Blog Not Found');\n}\n\n// after: distinguish missing blog from empty blog\nif (!response.data.response) {\n    throw new Error(`Blog Not Found: ${JSON.stringify(response.data.meta || response.data).slice(0, 200)}`);\n}\nif (response.data.response.posts.length === 0) {\n    throw new Error('Blog has no posts');\n}","handlingStrategy":"validation","validationCode":"function blogHasPosts(data: { response?: { posts?: unknown[] } }): boolean {\n    return Boolean(data?.response?.posts && data.response.posts.length > 0);\n}","typeGuard":"interface LofterUserResponse { response: { posts: unknown[] } }\nfunction isLofterUserResponse(d: unknown): d is LofterUserResponse {\n    return typeof d === 'object' && d !== null && Array.isArray((d as any)?.response?.posts);\n}","tryCatchPattern":"try {\n    return await fetchLofterUser(name);\n} catch (e) {\n    if (e instanceof Error && /Blog Not Found/.test(e.message)) {\n        return { notFound: true, name };\n    }\n    throw e;\n}","preventionTips":["Confirm the blog URL resolves before subscribing.","Distinguish 'no blog' from 'no posts' for clearer UX.","Inspect the full API envelope to catch envelope-shape changes."],"tags":["upstream-change","api-envelope","lofter","not-found"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}