{"record":{"id":"4d4c3dc3fd46ea9d","repo":"jackwener/OpenCLI","slug":"http-probe-httpstatus-from-zsxq-v2-users-self","errorCode":null,"errorMessage":"HTTP ${probe.httpStatus} from zsxq /v2/users/self","messagePattern":"HTTP (.+?) from zsxq /v2/users/self","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/zsxq/auth.js","lineNumber":37,"sourceCode":"          headers: { Accept: 'application/json' },\n        });\n        if (r.status === 401 || r.status === 403) {\n          return { kind: 'auth', detail: 'zsxq /v2/users/self returned HTTP ' + r.status };\n        }\n        if (!r.ok) return { kind: 'http', httpStatus: r.status };\n        const d = await r.json();\n        if (d?.succeeded === false || !d?.resp_data?.user) {\n          return { kind: 'auth', detail: 'zsxq /v2/users/self returned succeeded=false — anonymous' };\n        }\n        const u = d.resp_data.user;\n        return { ok: true, user_id: String(u.user_id || u.id || ''), name: String(u.name || u.nickname || '') };\n      } catch (e) {\n        return { kind: 'exception', detail: String(e && e.message || e) };\n      }\n    })()\n  `);\n  if (probe?.kind === 'auth') throw new AuthRequiredError('zsxq.com', probe.detail);\n  if (probe?.kind === 'http') throw new CommandExecutionError(`HTTP ${probe.httpStatus} from zsxq /v2/users/self`);\n  if (probe?.kind === 'exception') throw new CommandExecutionError(`zsxq whoami failed: ${probe.detail}`);\n  if (!probe?.ok) throw new CommandExecutionError(`Unexpected zsxq probe: ${JSON.stringify(probe)}`);\n  if (!probe.user_id) {\n    throw new AuthRequiredError('zsxq.com', 'zsxq /v2/users/self 200 but user_id missing — incomplete session');\n  }\n  return { user_id: probe.user_id, name: probe.name };\n}\n\nregisterSiteAuthCommands({\n  site: 'zsxq',\n  domain: 'zsxq.com',\n  loginUrl: 'https://wx.zsxq.com/login',\n  columns: ['user_id', 'name'],\n  verify: verifyZsxqIdentity,\n  // No-navigation poll: probe the API from the current page so the login-page\n  // QR code isn't reset by a goto on every interval.\n  poll: async (page) => {\n    const loggedIn = await page.evaluate(`(async () => {","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/zsxq/auth.js#L19-L55","documentation":"When the /v2/users/self probe returns a non-auth HTTP failure (e.g. 403, 429, 5xx), verifyZsxqIdentity throws CommandExecutionError with the status code in the message. Unlike AuthRequiredError this signals a transport/HTTP-level problem reaching or processing the endpoint, not necessarily a login issue.","triggerScenarios":"The probe's HTTP request to https://api.zsxq.com/v2/users/self completes but with a status that is neither a recognized auth failure nor 200 — e.g. 403 rate-limit/WAF block, 500 server error, or a proxy intercepting the request.","commonSituations":"zsxq API rate limiting automated requests; CDN/WAF blocking headless browser fingerprints; network proxies returning error pages; transient zsxq server-side incidents.","solutions":["Inspect httpStatus in the message; retry after backoff for 429/5xx responses.","Ensure the request goes through a real logged-in browser context with a normal User-Agent, not a blocked headless fingerprint.","Test the endpoint manually in the same browser profile (fetch('/v2/users/self')) to see the raw response.","Check zsxq service status or try later if it is a server-side (5xx) failure."],"exampleFix":"// before\nconst id = await verifyZsxqIdentity(page);\n// after\ntry {\n  const id = await verifyZsxqIdentity(page);\n} catch (e) {\n  if (/HTTP 429|HTTP 5\\d\\d/.test(e.message)) {\n    await new Promise(r => setTimeout(r, 5000));\n    return verifyZsxqIdentity(page);\n  }\n  throw e;\n}","handlingStrategy":"retry","validationCode":"const r = await page.request.get('https://api.zsxq.com/v2/users/self');\nif ([403, 429].includes(r.status())) await sleep(5000); // back off before retry","typeGuard":"const isHttpProbeError = (e) => /^HTTP \\d{3} from zsxq/.test(e?.message || '');","tryCatchPattern":"try {\n  return await verifyZsxqIdentity(page);\n} catch (e) {\n  if (isHttpProbeError(e) && /HTTP (429|5\\d\\d)/.test(e.message)) {\n    await sleep(5000);\n    return verifyZsxqIdentity(page);\n  }\n  throw e;\n}","preventionTips":["Throttle zsxq API calls to avoid 429 rate limits.","Run with a normal browser fingerprint/User-Agent to avoid WAF blocks.","Monitor zsxq status during 5xx bursts instead of hammering retries."],"tags":["http","network","api"],"backgroundTag":"http-error-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}