DIYgod/RSSHub · error · Error
TechFlow API returned an unexpected non-JSON response.
Error message
TechFlow API returned an unexpected non-JSON response.
What it means
Thrown by techflowpost/utils.ts:91 via `throw new Error(...)` (NOT an InvalidParameterError) when the TechFlow API returns a string body that is NOT the expected Aliyun acw_sc__v2 anti-bot challenge. Flow: first request returns JSON -> return it; if it returns a string, the code assumes it is the acw_sc__v2 challenge page and looks for `var arg1='...'` to derive a cookie via getAcwScV2Cookie. If arg1 is not found, the string is some OTHER non-JSON response (error page, maintenance page, different challenge) and this error fires. A follow-up TypeError at line 97 covers the case where the retry still returns a string. The derived acwScV2Cookie is module-level and reused across calls.
Source
Thrown at lib/routes/techflowpost/utils.ts:91
}
return `acw_sc__v2=${getAcwScV2ByArg1(arg1)}`;
}
async function requestApi<T>(endpoint: string, referer: string, searchParams?: Record<string, string | number | boolean>) {
const request = () =>
got.get(`${apiRootUrl}${endpoint}`, {
searchParams,
headers: getHeaders(referer),
});
const { data } = await request();
if (typeof data !== 'string') {
return data as T;
}
const cookie = getAcwScV2Cookie(data);
if (!cookie) {
throw new Error('TechFlow API returned an unexpected non-JSON response.');
}
acwScV2Cookie = cookie;
const retryResponse = await request();
if (typeof retryResponse.data === 'string') {
throw new TypeError('TechFlow API still returned an anti-crawler challenge after retry.');
}
return retryResponse.data as T;
}
function getPictureUrl(picture?: string) {
if (!picture) {
return;
}
return new URL(picture, uploadRootUrl).href;
}
View on GitHub (pinned to bed535e087)
Solutions
- Reproduce the request with the same UA/headers and inspect the raw string body to see what is actually being returned.
- If the challenge format changed, update getAcwScV2Cookie / getAcwScV2ByArg1 to match the new arg1 extraction and decoding.
- If transient (maintenance or Cloudflare burst), retry later.
- Confirm config.trueUA is being sent (getHeaders sets it) — a non-realistic UA often triggers a stricter challenge.
Example fix
// before
const cookie = getAcwScV2Cookie(data);
if (!cookie) {
throw new Error('TechFlow API returned an unexpected non-JSON response.');
}
// after (surface the actual body to speed up diagnosis)
const cookie = getAcwScV2Cookie(data);
if (!cookie) {
throw new Error(`TechFlow API returned an unexpected non-JSON response (first 200 chars): ${data.slice(0, 200)}`);
} Defensive patterns
Strategy: retry
Validate before calling
// You cannot fully pre-validate an anti-bot challenge; sanity-check inputs instead.
// Ensure a realistic UA is sent (config.trueUA) and the referer matches the site.
function hasRealisticHeaders(headers: Record<string, string>): boolean {
return Boolean(headers['user-agent']) && Boolean(headers['referer']);
} Type guard
function isAcwScV2Challenge(body: string): boolean {
return typeof body === 'string' && /var arg1='[^']*';/.test(body);
} Try / catch
// Anti-bot failures are often transient — retry with backoff, refresh the cookie each time.
async function requestWithRetry<T>(endpoint: string, referer: string, attempts = 3): Promise<T> {
for (let i = 0; i < attempts; i++) {
try {
return await requestApi<T>(endpoint, referer);
} catch (e) {
const last = i === attempts - 1;
if (last || !(e instanceof Error) || !/unexpected non-JSON/i.test(e.message)) throw e;
acwScV2Cookie = ''; // force a fresh challenge solve
await wait(Math.pow(2, i) * 1000); // host-provided wait primitive
}
}
} Prevention
- Always send config.trueUA and a matching Referer (getHeaders already does this).
- If the site drops acw_sc__v2, update getAcwScV2Cookie / getAcwScV2ByArg1 to the new challenge.
- Reset the module-level acwScV2Cookie on failure so retries solve a fresh challenge.
When it happens
Trigger: TechFlow swaps its WAF/challenge mechanism away from acw_sc__v2; the API returns an HTML error or maintenance page; a Cloudflare interstitial is served; getAcwScV2ByArg1 (imported from ../5eplay/utils) no longer matches the site's current arg1 algorithm.
Common situations: Site provider changes anti-bot vendor; scheduled maintenance returning a static page; the acw_sc__v2 algorithm is versioned and the decoder is stale; config.trueUA not sent so a stricter challenge is returned.
Related errors
- Cannot get the redirect link
- TechFlow API still returned an anti-crawler challenge after
- 访问量过大,触发验证码
- 文章列表获取失败,可能是被临时限制了访问,请稍后重试 ${JSON.stringify(resp.data)}
- No article URL found for article with id ${id}
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/cfd5b328ec78e8ef.
Report an issue: GitHub.