{"record":{"id":"3eb11a745c624c20","repo":"DIYgod/RSSHub","slug":"invalid-id-3eb11a","errorCode":null,"errorMessage":"Invalid id","messagePattern":"Invalid id","errorType":"validation","errorClass":"InvalidParameterError","httpStatus":null,"severity":"warning","filePath":"lib/routes/mirror/index.ts","lineNumber":35,"sourceCode":"    example: '/mirror/tingfei.eth',\n    parameters: { id: 'user id' },\n    features: {\n        requireConfig: false,\n        requirePuppeteer: false,\n        antiCrawler: false,\n        supportBT: false,\n        supportPodcast: false,\n        supportScihub: false,\n    },\n    name: 'User',\n    maintainers: ['fifteen42', 'rde9', 'nczitzk'],\n    handler,\n};\n\nasync function handler(ctx) {\n    const id = ctx.req.param('id');\n    if (!id.endsWith('.eth') && !isValidHost(id)) {\n        throw new InvalidParameterError('Invalid id');\n    }\n    const rootUrl = 'https://mirror.xyz';\n    const currentUrl = id.endsWith('.eth') ? `${rootUrl}/${id}` : `https://${id}.mirror.xyz`;\n\n    const response = await got(currentUrl);\n\n    const data = JSON.parse(response.data.match(/\"__NEXT_DATA__\" type=\"application\\/json\">(\\{\"props\":.*\\})<\\/script>/)[1]);\n\n    const items = Object.keys(data.props.pageProps.__APOLLO_STATE__)\n        .filter((key) => key.startsWith('entry:'))\n        .map((key) => {\n            const item = data.props.pageProps.__APOLLO_STATE__[key];\n            return {\n                title: item.title,\n                description: md.render(item.body),\n                link: `${currentUrl}/${item._id}`,\n                pubDate: parseDate(item.publishedAtTimestamp, 'X'),\n                author: data.props.pageProps.publicationLayoutProject.displayName,","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/mirror/index.ts#L17-L53","documentation":"Thrown as InvalidParameterError by the Mirror.xyz user route when the :id path parameter neither ends with '.eth' nor passes utils.isValidHost(id). The route accepts either an ENS name (foo.eth) or a plain hostname (used as a custom subdomain foo.mirror.xyz). Anything else — URL-encoded slashes, path-like segments, TLDs isValidHost rejects — is rejected before any fetch.","triggerScenarios":"Caller requests /mirror/<id> where id is, e.g., 'foo/bar', contains characters isValidHost disallows (underscores, leading hyphen, non-ASCII without punycode), or is a full URL like 'https://foo.eth'. The check `!id.endsWith('.eth') && !isValidHost(id)` is true, so it throws.","commonSituations":"User pastes a full mirror.xyz URL into the path; user passes a publication subdomain that contains an underscore (commonly invalid for hostnames); user encodes the id with %2F; the id is empty.","solutions":["Use a bare ENS name ending in .eth, e.g. /mirror/tingfei.eth.","If using a custom subdomain, pass only the host label (e.g. 'myblog') that would form myblog.mirror.xyz and ensure it is a syntactically valid hostname (letters/digits/hyphens, no underscores).","Strip any leading 'https://' or trailing slash before the id reaches the route (fix the client/feed-URL construction).","If the publication genuinely uses an underscore subdomain, that is currently unsupported — file an issue or use the .eth form."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import { isValidHost } from '@/utils/valid-host';\nconst id = ctx.req.param('id');\nconst isEns = id.endsWith('.eth');\nconst isHost = isValidHost(id);\nif (!isEns && !isHost) {\n    throw new InvalidParameterError(`Invalid id '${id}'. Use an ENS name ending in .eth or a valid hostname label.`);\n}","typeGuard":"function isMirrorId(id: string): boolean {\n    return typeof id === 'string' && (id.endsWith('.eth') || /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i.test(id));\n}","tryCatchPattern":null,"preventionTips":["Construct feed URLs from the publication's canonical id only, never a full URL.","Document the two accepted forms (ENS vs hostname label) clearly in the route description.","Reject path-like inputs (containing '/') early in any client that builds the feed URL."],"tags":["invalid-parameter","validation","hostname","ens","mirror"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}