{"record":{"id":"a647b7838200cae9","repo":"DIYgod/RSSHub","slug":"unable-to-discover-the-current-locals-feed-action","errorCode":null,"errorMessage":"Unable to discover the current Locals feed action id.","messagePattern":"Unable to discover the current Locals feed action id\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/locals/feed.ts","lineNumber":277,"sourceCode":"function 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}\n\nfunction getTitle(post: LocalsPost) {\n    const textFallback = post.text\n        ?.replaceAll(/<[^>]+>/g, '\\n')\n        .split('\\n')\n        .map((line) => line.trim())\n        .find(Boolean);\n    return post.title || post.subtitle || textFallback || post.share_url || 'Locals post';\n}","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/locals/feed.ts#L259-L295","documentation":"Thrown by `resolveActionIds` (lib/routes/locals/feed.ts:276) when the serverApi JS asset was fetched successfully but `extractFeedActionId(assetContent)` returned null. The action id is extracted from the bundle source; a null result means the regex/anchor used to find it no longer matches the current minified code.","triggerScenarios":"The serverApi bundle is re-minified and the literal `extractFeedActionId` searches for (e.g. an action name or numeric id) is gone or renamed; the wrong asset was selected; the asset body is an error/redirect document rather than JS.","commonSituations":"Locals ships a new server-api version; bundler reorders identifiers; the asset URL resolved relative to `rootUrl` incorrectly and fetched a fallback page.","solutions":["Fetch the resolved asset URL directly in a browser and grep its source for the current feed action id pattern.","Update `extractFeedActionId`'s regex/anchor to the new identifier.","Cache-bust `locals:action-ids:<community>` after the fix.","Verify `new URL(serverApiAsset, rootUrl).href` resolves to a `.js` document, not HTML."],"exampleFix":"// before: a single fixed regex inside extractFeedActionId that no longer matches\n// after: try several known anchor shapes, fall back to scanning numeric ids\nfunction extractFeedActionId(assetContent: string): string | null {\n    const patterns = [\n        /feedActionId[\"']?\\s*[:=]\\s*[\"'](\\d+)[\"']/,\n        /action[\"']\\s*,\\s*id[\"']\\s*[:=]\\s*(\\d+)/,\n        /\"(\\d{6,})\"[^}]{0,40}feed/,\n    ];\n    for (const re of patterns) {\n        const m = assetContent.match(re);\n        if (m) return m[1];\n    }\n    return null;\n}","handlingStrategy":"validation","validationCode":"function feedActionIdParsable(assetContent: string): boolean {\n    return extractFeedActionId(assetContent) !== null;\n}\nif (!feedActionIdParsable(assetContent)) {\n    throw new TypeError('Locals serverApi bundle changed; feed action id not found');\n}","typeGuard":"function isActionId(value: string | null | undefined): value is string {\n    return typeof value === 'string' && /^\\d+$/.test(value);\n}","tryCatchPattern":"try {\n    return await resolveActionIds(community, session);\n} catch (e) {\n    if (e instanceof Error && /Unable to discover the current Locals feed action id/.test(e.message)) {\n        await cache.delete('locals:action-ids:' + community);\n        return await resolveActionIds(community, session);\n    }\n    throw e;\n}","preventionTips":["Maintain multiple anchor regexes in `extractFeedActionId`.","Pin the action-id cache to a short TTL.","Capture a bundle fixture for regression testing."],"tags":["upstream-change","regex","asset-bundle","locals"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}