{"record":{"id":"23b6f27361f15fa2","repo":"jackwener/OpenCLI","slug":"auth-hint","errorCode":null,"errorMessage":"AUTH_HINT","messagePattern":"AUTH_HINT","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"critical","filePath":"clis/quark/utils.js","lineNumber":22,"sourceCode":"export const TASK_API = 'https://drive-pc.quark.cn/1/clouddrive/task';\nconst QUARK_DOMAIN = 'pan.quark.cn';\nconst AUTH_HINT = 'Quark Drive requires a logged-in browser session';\nfunction isAuthFailure(message, status) {\n    if (status === 401 || status === 403)\n        return true;\n    return /not logged in|login required|please log in|authentication required|unauthorized|forbidden|未登录|请先登录|需要登录|登录/.test(message.toLowerCase());\n}\nfunction getErrorStatus(error) {\n    if (!error || typeof error !== 'object' || !('status' in error))\n        return undefined;\n    const status = error.status;\n    return typeof status === 'number' ? status : undefined;\n}\nfunction unwrapApiData(resp, action) {\n    if (resp.status === 200)\n        return resp.data;\n    if (isAuthFailure(resp.message, resp.status)) {\n        throw new AuthRequiredError(QUARK_DOMAIN, AUTH_HINT);\n    }\n    throw new CommandExecutionError(`quark: ${action}: ${resp.message}`);\n}\nexport function extractPwdId(url) {\n    const m = url.match(/\\/s\\/([a-zA-Z0-9]+)/);\n    if (m)\n        return m[1];\n    if (/^[a-zA-Z0-9]+$/.test(url))\n        return url;\n    throw new ArgumentError(`Invalid Quark share URL: ${url}`);\n}\nexport async function fetchJson(page, url, options) {\n    const method = options?.method || 'GET';\n    const body = options?.body ? JSON.stringify(options.body) : undefined;\n    const js = `fetch(${JSON.stringify(url)}, {\n    method: ${JSON.stringify(method)},\n    headers: { 'Content-Type': 'application/json' },\n    credentials: 'include',","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/quark/utils.js#L4-L40","documentation":"unwrapApiData in clis/quark/utils.js raises AuthRequiredError with the placeholder message AUTH_HINT whenever isAuthFailure(resp.message, resp.status) detects the Quark API response indicates an authentication problem (e.g. not-logged-in / credential-expired messages or status codes). Called by apiGet, apiPost, getToken, and files, this is the central auth gate for the Quark CLI, signaling that the user must re-authenticate in the browser session before requests can succeed.","triggerScenarios":"Any apiGet/apiPost (rename, delete, save, mv, listing) where Quark responds with an auth-failure message or status — typically an expired login session cookie in the controlled browser page; getToken hitting the share token endpoint while logged out.","commonSituations":"Browser session cookies expired after inactivity; Quark logged out the session elsewhere; running the CLI after a long gap; account security logout; using a page that was never logged in.","solutions":["Re-authenticate: open the Quark drive in the CLI-controlled browser page and log in again, then retry the command.","Clear stale session state/cookies for QUARK_DOMAIN and log in fresh.","Verify the account is still logged in on quark.cn in a normal browser; re-login there if needed.","Check whether Quark changed its auth-failure message/status codes, which would require updating isAuthFailure detection.","Run a lightweight listing command (files) first to validate the session before long operations."],"exampleFix":"// before (response surfaced as generic CommandExecutionError)\nthrow new CommandExecutionError(`quark: ${action}: ${resp.message}`);\n// after (already handled by the library)\nif (isAuthFailure(resp.message, resp.status)) {\n  throw new AuthRequiredError(QUARK_DOMAIN, AUTH_HINT);\n}","handlingStrategy":"try-catch","validationCode":"// session probe before heavy operations\ntry {\n  await files(page, { fid: '0' });\n} catch (e) {\n  if (e instanceof AuthRequiredError) {\n    await reloginInBrowser(page, QUARK_DOMAIN);\n  }\n}","typeGuard":"function isAuthRequiredError(e) {\n  return e instanceof AuthRequiredError ||\n    (e && typeof e.message === 'string' && e.message.includes('login'));\n}","tryCatchPattern":"try {\n  await apiCall(page, ...);\n} catch (e) {\n  if (isAuthRequiredError(e)) {\n    await reloginInBrowser(page, QUARK_DOMAIN);\n    return apiCall(page, ...); // retry once after re-auth\n  }\n  throw e;\n}","preventionTips":["Re-login in the controlled browser session before long-running jobs.","Probe the session with a cheap listing call before bulk operations.","Keep the browser profile/cookies persistent to reduce login churn.","Watch for Quark auth-message changes and update isAuthFailure."],"tags":["authentication","session-expired","quark"],"backgroundTag":"auth-session-expired","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}