{"record":{"id":"ec04b732d7d6776f","repo":"DIYgod/RSSHub","slug":"invalid-community-community","errorCode":null,"errorMessage":"Invalid community: ${community}","messagePattern":"Invalid community: (.+?)","errorType":"exception","errorClass":"InvalidParameterError","httpStatus":null,"severity":"warning","filePath":"lib/routes/lemmy/index.ts","lineNumber":68,"sourceCode":"            },\n        ],\n        requirePuppeteer: false,\n        antiCrawler: false,\n        supportBT: false,\n        supportPodcast: false,\n        supportScihub: false,\n    },\n    name: 'Community',\n    maintainers: ['wb14123', 'pseudoyu'],\n    handler,\n};\n\nasync function handler(ctx) {\n    const sort = ctx.req.param('sort') ?? 'Active';\n    const community = ctx.req.param('community');\n    const communitySlices = community.split('@');\n    if (communitySlices.length !== 2) {\n        throw new InvalidParameterError(`Invalid community: ${community}`);\n    }\n    const instance = community.split('@', 2)[1];\n    const allowedDomain = ['lemmy.world', 'lemm.ee', 'lemmy.ml', 'sh.itjust.works', 'feddit.de', 'hexbear.net', 'beehaw.org', 'lemmynsfw.com', 'lemmy.ca', 'programming.dev'];\n    if (!config.feature.allow_user_supply_unsafe_domain && !allowedDomain.includes(new URL(`http://${instance}/`).hostname)) {\n        throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);\n    }\n\n    const communityUrl = `https://${instance}/api/v3/community?name=${community}`;\n    const communityData = await cache.tryGet(communityUrl, async () => {\n        const result = await got({ method: 'get', url: communityUrl, headers: { 'Content-Type': 'application/json' } });\n        return result.data.community_view.community;\n    });\n\n    const postUrl = `https://${instance}/api/v3/post/list?type_=All&sort=${sort}&community_name=${community}&limit=50`;\n    const postData = await cache.tryGet(\n        postUrl,\n        async () => {\n            const result = await got({ method: 'get', url: postUrl, headers: { 'Content-Type': 'application/json' } });","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/lemmy/index.ts#L50-L86","documentation":"Thrown by the lemmy route handler as InvalidParameterError when the `community` path param does not contain exactly one '@' — i.e. it is not in the required name@instance format. The handler splits on '@' and requires exactly 2 parts; any other count (0 or 2+ '@' signs) is rejected before any network call.","triggerScenarios":"Request to /lemmy/<community>/<sort> where <community> lacks the @instance suffix (e.g. 'programming' instead of 'programming@programming.dev'), or contains multiple '@' signs (e.g. 'a@b@c'). The split must yield exactly ['name','instance'].","commonSituations":"User omits the instance (most common — many users assume a default instance); copy-paste truncates the community name; URL encoding mangles the '@' (e.g. %40 handled differently); trailing slash creating an empty segment.","solutions":["Provide the community in name@instance form, e.g. /lemmy/programming@programming.dev/Hot","If you want a default instance, wrap the route or pre-process the param before calling the handler","Validate/normalize the param at the proxy layer for self-hosters","Check for URL-encoded '@' (%40) if the literal isn't coming through"],"exampleFix":"// before\nconst communitySlices = community.split('@');\nif (communitySlices.length !== 2) {\n    throw new InvalidParameterError(`Invalid community: ${community}`);\n}\n// after — clearer message + accept %40\nconst normalized = community.replaceAll('%40', '@');\nconst communitySlices = normalized.split('@');\nif (communitySlices.length !== 2) {\n    throw new InvalidParameterError(`Invalid community '${community}'. Expected format: name@instance (e.g. programming@programming.dev)`);\n}","handlingStrategy":"validation","validationCode":"function parseCommunity(raw: string): { name: string; instance: string } {\n  const norm = raw.replaceAll('%40', '@');\n  const parts = norm.split('@');\n  if (parts.length !== 2 || !parts[0] || !parts[1]) {\n    throw new Error(`community '${raw}' must be name@instance`);\n  }\n  return { name: parts[0], instance: parts[1] };\n}","typeGuard":"function isCommunityFormat(v: unknown): v is string {\n  if (typeof v !== 'string') return false;\n  const parts = v.replaceAll('%40', '@').split('@');\n  return parts.length === 2 && parts[0].length > 0 && parts[1].length > 0;\n}","tryCatchPattern":"try { return await handler(ctx); }\ncatch (e) {\n  if (e instanceof InvalidParameterError && /Invalid community/.test(e.message)) {\n    return ctx.json({ error: e.message, format: 'name@instance' }, 400);\n  }\n  throw e;\n}","preventionTips":["Normalize URL-encoded '@' (%40) before splitting","Reject empty name or instance segments, not just wrong part count","Provide example values in the error message","Default to a known instance if your deployment wants one"],"tags":["validation","parameter","format","fediverse"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}