{"record":{"id":"df59f2b96b29606e","repo":"DIYgod/RSSHub","slug":"unknown-type-type-df59f2","errorCode":null,"errorMessage":"Unknown type: ${type}","messagePattern":"Unknown type: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"warning","filePath":"lib/routes/fantia/search.ts","lineNumber":212,"sourceCode":"            items = response.data.products.map((item) => ({\n                title: item.name,\n                link: `${rootUrl}/products/${item.id}`,\n                author: item.fanclub.fanclub_name_with_creator_name,\n                description: `${item.buyable_lowest_plan.description ? `<p>${item.buyable_lowest_plan.description}</p>` : ''}<img src=\"${item.thumb ? item.thumb.main : item.thumb_micro}\">`,\n            }));\n            break;\n\n        case 'commissions':\n            items = response.data.commissions.map((item) => ({\n                title: item.name,\n                link: `${rootUrl}/commissions/${item.id}`,\n                author: item.fanclub.fanclub_name_with_creator_name,\n                description: `${item.buyable_lowest_plan.description ? `<p>${item.buyable_lowest_plan.description}</p>` : ''}<img src=\"${item.thumb ? item.thumb.main : item.thumb_micro}\">`,\n            }));\n            break;\n\n        default:\n            throw new Error(`Unknown type: ${type}`);\n    }\n\n    return {\n        title: `Fantia - Search ${type}`,\n        link: apiUrl.replace('api/v1/search/', ''),\n        item: items,\n    };\n}\n","sourceCodeStart":194,"sourceCodeEnd":221,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/fantia/search.ts#L194-L221","documentation":"Thrown by the Fantia search route's switch statement when the `type` path parameter does not match any of the four known cases (`fanclubs`, `posts`, `products`, `commissions`). This is a validation gap: the error fires only AFTER the upstream API has already been called (the URL is built with the unvalidated type), so an invalid type wastes a network request before failing. The default case should ideally be unreachable since the parameter defaults to `'posts'`, but a user can override it with any string.","triggerScenarios":"A user passes an unsupported type value like `/fantia/search/fanclub` (missing 's'), `/fantia/search/article`, or any arbitrary string. The API call to `fantia.jp/api/v1/search/<type>` is made first, and since the response won't have the expected data shape, the switch default case throws.","commonSituations":"User misspells a type value (e.g., `fanclub` vs `fanclubs`). User passes a type from a different Fantia API version. The route documentation table is consulted but the user misreads the mapping.","solutions":["Use one of the four valid type values: `fanclubs`, `posts`, `products`, or `commissions`.","Omit the type parameter to default to `posts`.","Add pre-validation with a Set check before the API call to fail fast and avoid wasting a network request."],"exampleFix":"// before — type is used in the API URL without validation\nconst type = ctx.req.param('type') || 'posts';\n// ... API call happens ...\nswitch (type) {\n    // ...\n    default:\n        throw new Error(`Unknown type: ${type}`);\n}\n\n// after — validate before making the network request\nconst validTypes = new Set(['fanclubs', 'posts', 'products', 'commissions']);\nconst type = ctx.req.param('type') || 'posts';\nif (!validTypes.has(type)) {\n    throw new InvalidParameterError(`Unknown type: ${type}. Valid types: ${[...validTypes].join(', ')}`);\n}","handlingStrategy":"validation","validationCode":"const VALID_SEARCH_TYPES = new Set(['fanclubs', 'posts', 'products', 'commissions']);\n\nfunction validateSearchType(type: string | undefined): string {\n    const resolved = type ?? 'posts';\n    if (!VALID_SEARCH_TYPES.has(resolved)) {\n        throw new InvalidParameterError(`Unknown type: ${type}. Valid: fanclubs, posts, products, commissions`);\n    }\n    return resolved;\n}","typeGuard":"type SearchType = 'fanclubs' | 'posts' | 'products' | 'commissions';\n\nfunction isSearchType(value: string): value is SearchType {\n    return ['fanclubs', 'posts', 'products', 'commissions'].includes(value);\n}","tryCatchPattern":null,"preventionTips":["Validate the type parameter BEFORE constructing the API URL to fail fast.","Use only the four documented type values.","Default to 'posts' when the type is omitted.","Move the Set check above the got() call to avoid wasting a network request on invalid input."],"tags":["parameter-validation","validation-gap","enum-check","fantia"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}