{"record":{"id":"99dc7fe2455e91d5","repo":"DIYgod/RSSHub","slug":"unable-to-locate-the-current-locals-serverapi-asse","errorCode":null,"errorMessage":"Unable to locate the current Locals serverApi asset.","messagePattern":"Unable to locate the current Locals serverApi asset\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/locals/feed.ts","lineNumber":268,"sourceCode":"                thumb: imageMatch?.[2],\n            },\n        },\n        hashtag: community,\n        id: Number(idMatch[1]),\n        title: titleMatch[1],\n    } satisfies LocalsCommunityInfo;\n}\n\nfunction fetchContentPage(community: string, session: string) {\n    return cache.tryGet(`locals:content-page:${community}`, () => ofetch(`${rootUrl}/${community}/feed?mode=content`, { headers: getRequestHeaders(session) }));\n}\n\nfunction resolveActionIds(community: string, session: string) {\n    return cache.tryGet(`locals:action-ids:${community}`, async () => {\n        const html = await fetchContentPage(community, session);\n        const serverApiAsset = extractAssetUrls(html).find((assetUrl) => assetUrl.includes('/serverApi-'));\n        if (!serverApiAsset) {\n            throw new Error('Unable to locate the current Locals serverApi asset.');\n        }\n\n        const assetContent = await ofetch(new URL(serverApiAsset, rootUrl).href, {\n            headers: getRequestHeaders(session),\n        });\n        const serverId = extractFeedActionId(assetContent);\n\n        if (!serverId) {\n            throw new Error('Unable to discover the current Locals feed action id.');\n        }\n\n        return serverId;\n    });\n}\n\nfunction getImage(post: LocalsPost) {\n    return post.photos?.[0]?.sizes?.full?.url || post.photos?.[0]?.sizes?.thumb?.url || post.previews?.[0]?.url || post.previews?.[0]?.first_frame_url || post.videos?.[0]?.preview || post.audios?.[0]?.preview;\n}","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/locals/feed.ts#L250-L286","documentation":"Thrown by `resolveActionIds` (lib/routes/locals/feed.ts:267) when none of the asset URLs extracted from the content page contains the `/serverApi-` segment. That asset is fetched and scanned to discover the current feed action id; without it the server-function call cannot be assembled. Indicates Locals renamed/restructured its JS bundle or the page did not list script tags.","triggerScenarios":"Locals renames the bundle (e.g. `serverApi-` becomes `server-api.` or is inlined into a vendor chunk); the content page is a gate/error page with no script manifests; `extractAssetUrls` regex misses the new `<script src=...>` or `<link>` format.","commonSituations":"Build/deploy on locals.com changes chunk names; CDN serves a different HTML to RSSHub's UA; cached stale content page predates the rename.","solutions":["Cache-bust `locals:content-page:<community>` and `locals:action-ids:<community>`.","Open the content page in a browser, list all `<script>`/asset URLs, and confirm which now carries the server API code.","Update the `.find((assetUrl) => assetUrl.includes('/serverApi-'))` predicate or `extractAssetUrls` to the new naming.","Ensure `config.locals.session` is valid so the real page (with manifests) is served."],"exampleFix":"// before\nconst serverApiAsset = extractAssetUrls(html).find((assetUrl) => assetUrl.includes('/serverApi-'));\n\n// after: accept renamed bundle patterns\nconst serverApiAsset = extractAssetUrls(html).find((assetUrl) =>\n    /\\/server[-_]?(api|function)/i.test(assetUrl)\n);","handlingStrategy":"validation","validationCode":"function hasServerApiAsset(html: string): boolean {\n    return /\\/serverApi-/i.test(html);\n}\n// before resolving action ids:\nif (!hasServerApiAsset(html)) {\n    throw new TypeError('Locals page has no serverApi asset; bundle may have changed');\n}","typeGuard":"function isServerApiAsset(url: string): boolean {\n    return /\\/server[-_]?api/i.test(url);\n}","tryCatchPattern":"try {\n    return await resolveActionIds(community, session);\n} catch (e) {\n    if (e instanceof Error && /Unable to locate the current Locals serverApi asset/.test(e.message)) {\n        await cache.delete('locals:content-page:' + community);\n        return await resolveActionIds(community, session); // one retry on fresh HTML\n    }\n    throw e;\n}","preventionTips":["Cache the content page with a short TTL so bundle renames are picked up quickly.","Keep a fallback predicate list of known asset-name patterns.","Alert when the asset predicate stops matching so you catch upstream renames early."],"tags":["upstream-change","asset-bundle","locals","caching"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}