{"record":{"id":"ef8b0b50b6bb6938","repo":"DIYgod/RSSHub","slug":"unable-to-extract-creator-id","errorCode":null,"errorMessage":"Unable to extract creator ID","messagePattern":"Unable to extract creator ID","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/patreon/feed.tsx","lineNumber":134,"sourceCode":"    const link = `${baseUrl}/${creator}`;\n\n    const creatorData = (await cache.tryGet(`patreon:creator:${creator}`, async () => {\n        const response = await ofetch(link);\n\n        const $ = load(response);\n\n        const ogUrl = $('meta[property=\"og:url\"]').attr('content');\n        if (ogUrl?.startsWith(`${baseUrl}/cw/`)) {\n            const ogImage = $('meta[property=\"og:image\"]').attr('content');\n            const creatorId = decodeURIComponent(ogImage || '').match(/card-teaser-image\\/creator\\/(\\d+)/)?.[1];\n            if (creatorId) {\n                const creator = await ofetch(`${baseUrl}/api/campaigns/${creatorId}`);\n                return {\n                    id: creatorId,\n                    attributes: creator.data.attributes,\n                };\n            }\n            throw new Error('Unable to extract creator ID');\n        }\n\n        const nextData = JSON.parse($('#__NEXT_DATA__').text());\n        const bootstrapEnvelope = nextData.props.pageProps.bootstrapEnvelope;\n\n        return {\n            id: bootstrapEnvelope.pageBootstrap.campaign.data.id,\n            attributes: bootstrapEnvelope.pageBootstrap.campaign.data.attributes,\n        };\n    })) as CreatorData;\n\n    if (!creatorData.id) {\n        throw new Error('Creator not found');\n    }\n\n    let headers = {};\n    if (config.patreon?.sessionId) {\n        headers = {","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/patreon/feed.tsx#L116-L152","documentation":"Thrown by the Patreon creator extractor when the page is a /cw/ (campaigns) URL and the og:image URL does not contain a 'card-teaser-image/creator/{digits}' segment from which the numeric creator ID is regex-captured. Without that ID, the /api/campaigns/{id} lookup cannot run, so the route aborts.","triggerScenarios":"og:url starts with 'https://www.patreon.com/cw/' (the campaigns landing path) AND the og:image meta either is missing or its URL no longer matches /card-teaser-image\\/creator\\/(\\d+)/. The regex returns undefined, creatorId is falsy, and the throw fires.","commonSituations":"Patreon changed the og:image URL format for /cw/ pages (different CDN path, no creator ID embedded); the creator has no card-teaser image so og:image is empty; Patreon A/B-tested a different OG tag set on campaigns pages.","solutions":["Open the /cw/{creator} page and inspect the og:image meta to see whether the creator ID is still embedded in a different pattern.","Update the regex (line 126) to match the current og:image URL shape, or fall back to parsing __NEXT_DATA__ even for /cw/ pages.","If og:image is absent, use another field that carries the campaign ID (e.g. a link rel=canonical or an embedded JSON blob).","File/track an upstream-format-change issue and pin the route until fixed."],"exampleFix":"// before\nconst creatorId = decodeURIComponent(ogImage || '').match(/card-teaser-image\\/creator\\/(\\d+)/)?.[1];\nif (creatorId) {\n    /* ... fetch /api/campaigns/{id} ... */\n}\nthrow new Error('Unable to extract creator ID');\n\n// after — fall back to __NEXT_DATA__ campaign id when og:image lacks the id\nlet creatorId = decodeURIComponent(ogImage || '').match(/card-teaser-image\\/creator\\/(\\d+)/)?.[1];\nif (!creatorId) {\n    const nextData = JSON.parse($('#__NEXT_DATA__').text());\n    creatorId = nextData.props?.pageProps?.bootstrapEnvelope?.pageBootstrap?.campaign?.data?.id;\n}\nif (!creatorId) {\n    throw new Error('Unable to extract creator ID');\n}","handlingStrategy":"fallback","validationCode":"// Detect the /cw/ shape and whether og:image carries the id before extracting.\nfunction ogImageHasCreatorId(ogImage: string | undefined): boolean {\n    return Boolean(ogImage && /card-teaser-image\\/creator\\/\\d+/.test(decodeURIComponent(ogImage)));\n}","typeGuard":"const isCwUrl = (ogUrl: string | undefined, baseUrl: string): boolean =>\n    Boolean(ogUrl) && ogUrl!.startsWith(`${baseUrl}/cw/`);","tryCatchPattern":"try {\n    creatorData = await extractCreator(creator);\n} catch (e) {\n    if (e instanceof Error && /Unable to extract creator ID/.test(e.message)) {\n        // fall back to the generic __NEXT_DATA__ path even for /cw/ pages\n        creatorData = await extractCreatorViaNextData(creator);\n    } else throw e;\n}","preventionTips":["Add a fallback extraction path (e.g. __NEXT_DATA__) so a regex change does not break /cw/ pages.","Unit-test the og:image regex against captured real og:image URLs (snapshot).","Log the og:image URL when extraction fails to detect upstream format drift."],"tags":["scraping","upstream-change","regex","patreon","dom-parsing"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}