{"record":{"id":"ee38371fbdbd4db1","repo":"jackwener/OpenCLI","slug":"probe-detail-ee3837","errorCode":null,"errorMessage":"${probe.detail}","messagePattern":"\\$\\{probe\\.detail\\}","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/suno/auth.js","lineNumber":43,"sourceCode":"        return { kind: 'auth', detail: 'clerk.suno.com /v1/client HTTP ' + r.status };\n      }\n      if (!r.ok) return { kind: 'http', httpStatus: r.status };\n      const d = await r.json();\n      const sessions = d?.response?.sessions || [];\n      if (!Array.isArray(sessions) || sessions.length === 0) {\n        return { kind: 'auth', detail: 'clerk.suno.com sessions=[] — anonymous' };\n      }\n      const active = sessions.find(s => s.status === 'active') || sessions[0];\n      const user = active?.user;\n      if (!user?.id) {\n        return { kind: 'auth', detail: 'clerk.suno.com session present but no user.id — stale session' };\n      }\n      return { ok: true, user_id: String(user.id), name: String(user.username || '') };\n    } catch (e) {\n      return { kind: 'exception', detail: String(e && e.message || e) };\n    }\n  })()`);\n  if (probe?.kind === 'auth') throw new AuthRequiredError('suno.com', probe.detail);\n  if (probe?.kind === 'http') throw new CommandExecutionError(`HTTP ${probe.httpStatus} from clerk.suno.com`);\n  if (probe?.kind === 'exception') throw new CommandExecutionError(`Suno whoami failed: ${probe.detail}`);\n  if (!probe?.ok) throw new CommandExecutionError(`Unexpected Suno probe: ${JSON.stringify(probe)}`);\n  return { user_id: probe.user_id, name: probe.name };\n}\n\nregisterSiteAuthCommands({\n  site: 'suno',\n  domain: 'suno.com',\n  loginUrl: 'https://suno.com/?sign-in=true',\n  columns: ['user_id', 'name'],\n  quickCheck: hasSunoClerkCookie,\n  verify: verifySunoIdentity,\n  poll: async (page) => {\n    if (!await hasSunoClerkCookie(page)) {\n      throw new AuthRequiredError('suno.com', 'Waiting for Suno Clerk __session/__client cookie');\n    }\n    return verifySunoIdentity(page);","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/suno/auth.js#L25-L61","documentation":"When the in-page Clerk /v1/client probe returns kind 'auth' (HTTP 401/403, sessions=[] anonymous, or a session with no user.id), verifySunoIdentity re-throws that detail as an AuthRequiredError for suno.com. It means the browser reached Clerk but Clerk says there is no usable authenticated session.","triggerScenarios":"The `__session` cookie existed but Clerk rejected it (401/403), returned zero sessions, or returned a session object with no user.id (stale session) during verifySunoIdentity.","commonSituations":"Expired or revoked Clerk JWT that still sits in the cookie jar; Suno rotated Clerk instance keys; account signed out server-side (another device or password change); stale session record left after an incomplete login.","solutions":["Re-run the suno login flow to mint a fresh __session token","Clear cookies for suno.com and clerk.suno.com, then log in again","If 'stale session' repeats, sign out everywhere on Suno's web UI and log back in","Retry after confirming https://suno.com loads and shows you logged in in the same browser profile"],"exampleFix":"// before\nif (probe?.kind === 'auth') throw new AuthRequiredError('suno.com', probe.detail);\n// after (caller side recovery)\ntry { await cli('suno', 'whoami'); }\ncatch (e) { if (e instanceof AuthRequiredError) await cli('suno', 'login'); }","handlingStrategy":"try-catch","validationCode":"// Verify auth with a cheap call first\ntry { await cli('suno', 'whoami'); } catch { await cli('suno', 'login'); }","typeGuard":"function isAuthRequiredError(e) {\n  return e instanceof Error && (e.name === 'AuthRequiredError' || /clerk\\.suno\\.com/.test(e.message));\n}","tryCatchPattern":"try {\n  const me = await cli('suno', 'whoami');\n} catch (e) {\n  if (isAuthRequiredError(e)) { await cli('suno', 'login'); return cli('suno', 'whoami'); }\n  throw e;\n}","preventionTips":["Re-login when Clerk sessions expire rather than retrying blindly","Sign out everywhere after credential changes to clear stale sessions","Keep one browser profile dedicated to opencli suno automation","Handle AuthRequiredError uniformly across your scripts to trigger re-login"],"tags":["auth","clerk","session-expired","suno"],"backgroundTag":"auth-session-expired","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}