DIYgod/RSSHub · error · Error
Unable to decode the Locals server response.
Error message
Unable to decode the Locals server response.
What it means
Thrown inside `parseUnknownResponse` after RSSHub executes Locals' obfuscated server-side JavaScript in a `node:vm` sandbox (lib/routes/locals/feed.ts:205). The sandboxed script is expected to populate `self.$R[instanceId][0]` with the decoded payload; if that slot is missing or falsy, the response shape has changed or the wrong `instanceId` was used. This is an upstream-format breakage, not a user input error.
Source
Thrown at lib/routes/locals/feed.ts:223
function parseUnknownResponse<T>(body: string, instanceId: string): T {
const sandbox = {
$R: {},
self: {},
} as {
$R: Record<string, unknown[]>;
self: {
$R?: Record<string, unknown[]>;
};
};
sandbox.self.$R = sandbox.$R;
vm.createContext(sandbox);
vm.runInContext(body, sandbox, { timeout: 5000 });
const value = sandbox.self.$R?.[instanceId]?.[0] as T | undefined;
if (!value) {
throw new Error('Unable to decode the Locals server response.');
}
return value;
}
function extractCommunityInfo(html: string, community: string) {
const markerIndex = html.indexOf(`hashtag:"${community}"`);
if (markerIndex === -1) {
throw new Error('Unable to resolve the Locals community metadata.');
}
const context = html.slice(Math.max(0, markerIndex - 200), markerIndex + 1200);
const idMatch = context.match(/id:(\d+)/);
const titleMatch = context.match(/title:"([^"]+)"/);
const descriptionMatch = context.match(/description:"([^"]*)"/);
const imageMatch = context.match(/image:\$R\[\d+\]=\{big:"([^"]*)",thumb:"([^"]*)"/);
if (!idMatch || !titleMatch) {View on GitHub (pinned to bed535e087)
Solutions
- Invalidate the Locals caches (`locals:action-ids:*`, `locals:content-page:*`) so a fresh bundle and server id are resolved.
- Inspect a raw `/_server` response in a browser devtools session and diff the `$R` assignment shape against `parseUnknownResponse`.
- Update the sandbox field access (`sandbox.self.$R?.[instanceId]?.[0]`) to match the new Locals serialization, or harden it to scan all `$R` entries.
- File an issue / open a PR against the `locals` route once the new format is confirmed.
Example fix
// before
const value = sandbox.self.$R?.[instanceId]?.[0] as T | undefined;
if (!value) {
throw new Error('Unable to decode the Locals server response.');
}
// after: scan every $R bucket for the first non-empty array entry
const allBuckets = Object.values(sandbox.self.$R ?? {});
const value = allBuckets.flatMap((b) => b).find(Boolean) as T | undefined;
if (!value) {
throw new Error('Unable to decode the Locals server response.');
} Defensive patterns
Strategy: try-catch
Validate before calling
// Cannot fully validate without executing the payload; pre-check the bundle freshness instead.
async function ensureFreshLocalsBundle(community: string): Promise<void> {
const page = await fetchContentPage(community, config.locals.session);
if (!/serverApi-/.test(page)) {
throw new Error('Locals bundle looks stale; refusing to call /_server');
}
} Type guard
function hasDecodedLocalsValue<T>(value: T | undefined): value is T {
return value !== undefined && value !== null;
} Try / catch
try {
return await requestServerFunction<T>(session, id, key, args);
} catch (e) {
if (e instanceof Error && /Unable to decode the Locals server response/.test(e.message)) {
await cache.delete('locals:action-ids:' + community);
// one retry with a freshly resolved bundle
return await requestServerFunction<T>(session, id, key, args);
}
throw e;
} Prevention
- Pin the bundle resolution behind a short-TTL cache so format drift surfaces fast.
- Log a snippet of the raw /_server body when decoding fails for faster triage.
- Subscribe to / watch the locals.com frontend releases; update the parser proactively.
When it happens
Trigger: Locals ships a new bundle that changes its `$R` serialization format, renames the `self.$R` global, or shifts the instance id mapping; the cached `serverId`/`key` passed as `instanceId` no longer matches the live response; the `/_server` endpoint returns an error body that still executes but writes nothing to `$R`.
Common situations: Site redesign or bundler output change on locals.com; stale cached action-id that mismatches the current bundle; A/B test variant served to RSSHub's IP/User-Agent.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Unable to resolve the Locals community metadata.
- Unable to locate the current Locals serverApi asset.
- Unable to discover the current Locals feed action id.
- 无法解析页面数据,请检查漫画 ID 是否正确或页面结构是否变动
- 无法解析页面 Props 数据
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/6d501740b73d0344.
Report an issue: GitHub.