{"record":{"id":"88d3ea311b84e1f8","repo":"DIYgod/RSSHub","slug":"error-88d3ea","errorCode":null,"errorMessage":"该用户运动日记为空","messagePattern":"该用户运动日记为空","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"lib/routes/keep/user.tsx","lineNumber":40,"sourceCode":"        },\n    ],\n    name: '运动日记',\n    maintainers: ['Dectinc', 'DIYgod'],\n    handler,\n};\n\nasync function handler(ctx) {\n    const id = ctx.req.param('id');\n\n    const response = await ofetch(`https://api.gotokeep.com/social/v3/people/${id}/home`, {\n        headers: {\n            Referer: `https://show.gotokeep.com/users/${id}`,\n        },\n    });\n\n    // check user have post or not\n    if (response.data.entries.length === 0) {\n        throw new Error('该用户运动日记为空');\n    }\n\n    const items = response.data.entries.flatMap((entry) =>\n        entry.entries.map((item) => {\n            let images: string[] = [];\n            if (item.images) {\n                images = item.meta.picture ? [item.meta.picture, ...item.images] : item.images;\n            } else if (item.meta.picture) {\n                images = [item.meta.picture];\n            }\n\n            const minute = Math.floor(item.meta.secondDuration / 60);\n            const second = item.meta.secondDuration - minute * 60;\n            return {\n                title: item.meta.title.trim(),\n                pubDate: item.created,\n                link: `https://show.gotokeep.com/entries/${item.id}`,\n                author: item.author.username,","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/keep/user.tsx#L22-L58","documentation":"Thrown by the Keep (fitness app) route when the user-profile API returns a non-empty response but response.data.entries is an empty array. This means the API call succeeded but the user has no workout diary entries to surface. The Chinese message translates to 'this user's workout diary is empty'.","triggerScenarios":"Calling /keep/user/:id for a user who has not published any workout entries, has set their diary to private (Keep may return empty instead of a permission error), or whose account has been deactivated. Also possible if the id is syntactically valid but does not correspond to any user, in which case Keep returns an empty entries array rather than a 404.","commonSituations":"A new Keep user who hasn't logged any workouts. A user who deleted all their posts. An incorrect ID that Keep silently resolves to an empty profile. The Keep API changed its response envelope and entries moved to a different field.","solutions":["Verify the user ID by visiting https://show.gotokeep.com/users/{id} in a browser — confirm the profile exists and has public workout entries.","If the user genuinely has no posts, this is expected behavior; consider using the route's allowEmpty option to return an empty feed instead of erroring.","If the API response shape changed, inspect response.data to find the new location of the entries array and update the accessor.","Add a separate check for a non-existent user (e.g. response.data error field) to distinguish 'no posts' from 'bad id'."],"exampleFix":"// before\nif (response.data.entries.length === 0) {\n    throw new Error('该用户运动日记为空');\n}\n\n// after — distinguish invalid user from empty diary\nif (!response.data || !response.data.entries) {\n    throw new Error(`Invalid Keep user id or API error for ${id}`);\n}\nif (response.data.entries.length === 0) {\n    return { title: `Keep user ${id}`, item: [], allowEmpty: true };\n}","handlingStrategy":"validation","validationCode":"const response = await ofetch(`https://api.gotokeep.com/social/v3/people/${id}/home`, { headers: { Referer: `...` } });\nif (!response?.data || !Array.isArray(response.data.entries)) {\n    throw new Error(`Unexpected Keep API response for user ${id}`);\n}\nif (response.data.entries.length === 0) {\n    // genuine empty diary — return empty feed instead of erroring\n    return { title: `Keep user ${id}`, item: [], allowEmpty: true };\n}","typeGuard":"function isKeepHomeResponse(r: unknown): r is { data: { entries: Array<{ entries: unknown[] }> } } {\n    return typeof r === 'object' && r !== null &&\n        'data' in r && Array.isArray((r as any).data?.entries);\n}","tryCatchPattern":null,"preventionTips":["Verify the user id resolves to a real profile before subscribing.","Differentiate 'no posts' from 'bad id' — Keep returns empty for both, so probe the profile separately if needed.","Consider returning allowEmpty feeds for genuinely-empty users to avoid erroring the RSS reader.","Watch for API envelope changes (entries moving to a different field)."],"tags":["api","empty-results","keep","user-content"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}