{"record":{"id":"e435d33ec773bfa4","repo":"DIYgod/RSSHub","slug":"cannot-find-the-script-with-data-iso-key-0","errorCode":null,"errorMessage":"Cannot find the script with data-iso-key=\"_0\"","messagePattern":"Cannot find the script with data-iso-key=\"_0\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/sciencedirect/call-for-paper.tsx","lineNumber":34,"sourceCode":"            source: ['sciencedirect.com'],\n        },\n    ],\n    name: 'Call for Papers',\n    maintainers: ['etShaw-zh'],\n    handler,\n    url: 'sciencedirect.com/browse/calls-for-papers',\n    description: '`sciencedirect.com/browse/calls-for-papers?subject=education` -> `/sciencedirect/call-for-paper/education`',\n};\n\nasync function handler(ctx) {\n    const { subject = '' } = ctx.req.param();\n    const apiUrl = `https://www.sciencedirect.com/browse/calls-for-papers?subject=${subject}`;\n    const response = await got(apiUrl);\n    const $ = load(response.body);\n\n    const scriptJSON = $('script[data-iso-key=\"_0\"]').text();\n    if (!scriptJSON) {\n        throw new Error('Cannot find the script with data-iso-key=\"_0\"');\n    }\n\n    let data;\n    try {\n        data = JSON.parse(JSON.parse(scriptJSON));\n    } catch (error: any) {\n        throw new Error(`Failed to parse embedded script JSON: ${error.message}`, { cause: error });\n    }\n\n    const cfpList = data?.callsForPapers?.list || [];\n    if (!cfpList.length) {\n        throw new Error('No Calls for Papers found');\n    }\n\n    const items = cfpList.map((cfp) => {\n        const link = `https://www.sciencedirect.com/special-issue/${cfp.contentId}/${cfp.url}`;\n        const description = renderToString(\n            <div>","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/sciencedirect/call-for-paper.tsx#L16-L52","documentation":"Thrown when the ScienceDirect calls-for-papers page contains no <script data-iso-key=\"_0\"> element whose text the route can harvest. ScienceDirect embeds its page data as a JSON blob inside such an ISO (Isomorphic) script tag; absence of the tag means the SSR payload structure changed or a non-content page was returned.","triggerScenarios":"GET https://www.sciencedirect.com/browse/calls-for-papers?subject={subject} returns HTML in which no script has data-iso-key=\"_0\". $('script[data-iso-key=\"_0\"]').text() is the empty string, so scriptJSON is falsy and the guard throws.","commonSituations":"ScienceDirect changed its isomorphic data-iso key scheme; the response was a bot-detection/consent page rather than the real page; a regional redirect served a different shell without the ISO blob; the subject value triggered an error page.","solutions":["Fetch the URL with a browser UA and confirm a script[data-iso-key] element is present; note any new key value.","If the key changed, update the selector to the new data-iso-key attribute.","If a consent/anti-bot page is returned, add the necessary cookies/headers or use config.trueUA.","Surface the HTTP status / partial body in the error to distinguish 'no script' from 'blocked'."],"exampleFix":"// before\nconst scriptJSON = $('script[data-iso-key=\"_0\"]').text();\nif (!scriptJSON) {\n    throw new Error('Cannot find the script with data-iso-key=\"_0\"');\n}\n\n// after — search all data-iso scripts for the one carrying callsForPapers\nlet scriptJSON = '';\nlet isoKey = '_0';\n$('script[data-iso-key]').each((_, el) => {\n    const txt = $(el).text();\n    if (txt.includes('callsForPapers')) {\n        scriptJSON = txt;\n        isoKey = $(el).attr('data-iso-key')!;\n        return false;\n    }\n});\nif (!scriptJSON) {\n    throw new Error('Cannot find a data-iso script carrying callsForPapers data');\n}","handlingStrategy":"fallback","validationCode":"// Verify the data-iso script presence with a browser-like UA before parsing.\nasync function hasIsoScript(subject: string): Promise<boolean> {\n    const html = await got(`https://www.sciencedirect.com/browse/calls-for-papers?subject=${subject}`, { headers: { 'user-agent': config.trueUA } }).then((r) => r.body);\n    return /<script[^>]*data-iso-key=/.test(html);\n}","typeGuard":"const hasIsoPayload = ($: cheerio.CheerioAPI): boolean =>\n    $('script[data-iso-key]').toArray().some((el) => $(el).text().length > 0);","tryCatchPattern":"try {\n    return await handler(ctx);\n} catch (e) {\n    if (e instanceof Error && /Cannot find the script with data-iso-key/.test(e.message)) {\n        // retry once with a full browser UA / consent cookies\n        return await handlerWithBrowserHeaders(ctx);\n    }\n    throw e;\n}","preventionTips":["Send config.trueUA and any required consent cookies to bypass anti-bot pages.","Search all data-iso scripts for the one carrying the relevant payload, rather than hard-coding _0.","Add an integration test against a live subject to catch selector drift."],"tags":["scraping","upstream-change","dom-parsing","sciencedirect","anti-bot"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}