{"record":{"id":"0be3645a7abadb9e","repo":"jackwener/OpenCLI","slug":"flomo-memos-requires-an-active-signed-in-flomo-bro","errorCode":null,"errorMessage":"Flomo memos requires an active signed-in Flomo browser session","messagePattern":"Flomo memos requires an active signed-in Flomo browser session","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/flomo/memos.js","lineNumber":174,"sourceCode":"    throw new CommandExecutionError(`Failed to fetch Flomo memos: ${err instanceof Error ? err.message : String(err)}`);\n  }\n  if (resp.status === 401 || resp.status === 403) {\n    throw new AuthRequiredError(FLOMO_API_DOMAIN, `Flomo API returned HTTP ${resp.status}; please refresh your Flomo login session`);\n  }\n  if (!resp.ok) {\n    throw new CommandExecutionError(`Flomo API returned HTTP ${resp.status}`);\n  }\n  try {\n    return await resp.json();\n  } catch (err) {\n    throw new CommandExecutionError(`Flomo API returned malformed JSON: ${err instanceof Error ? err.message : String(err)}`);\n  }\n}\n\nasync function readAccessToken(page) {\n  const token = unwrapBrowserResult(await page.evaluate(buildGetTokenJs()));\n  if (typeof token !== 'string' || !token.trim()) {\n    throw new AuthRequiredError(FLOMO_API_DOMAIN, 'Flomo memos requires an active signed-in Flomo browser session');\n  }\n  return token.trim();\n}\n\nconst command = cli({\n  site: 'flomo',\n  name: 'memos',\n  access: 'read',\n  description: 'List your Flomo memos',\n  domain: FLOMO_API_DOMAIN,\n  strategy: Strategy.COOKIE,\n  browser: true,\n  navigateBefore: `https://${FLOMO_APP_DOMAIN}/`,\n  args: [\n    { name: 'limit', type: 'int', default: 20, help: 'Number of memos to fetch (1-200)' },\n    { name: 'since', type: 'int', help: 'Only memos updated after this Unix timestamp in seconds' },\n    { name: 'slug', help: 'Pagination cursor from a previous memo page' },\n  ],","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/flomo/memos.js#L156-L192","documentation":"readAccessToken in clis/flomo/memos.js:174 evaluates injected JS in the Flomo browser page that reads the 'me' key from localStorage and extracts access_token. If the value is not a non-empty string — no signed-in session, missing/expired localStorage entry, or the page not being on the Flomo domain — it throws AuthRequiredError for the flomoapp.com domain. This command relies on cookie/session-based auth from a real browser session rather than a static API key.","triggerScenarios":"Running the flomo memos command when the automation browser has no active Flomo login: never logged in, session expired, localStorage 'me' key cleared or lacking access_token, or the navigation to v.flomoapp.com redirected to a login page.","commonSituations":"First run of the CLI without completing Flomo login in the managed browser; Flomo session expiring after inactivity or a password change; running headless with a fresh/ephemeral browser profile; clearing browser data or switching profiles.","solutions":["Open https://v.flomoapp.com/ in the automation browser and sign in to Flomo manually (complete 2FA/CAPTCHA if prompted), then re-run the command","Verify localStorage.getItem('me') on v.flomoapp.com contains access_token (possibly nested under .data) — log in again if missing","Use a persistent browser profile so the Flomo session survives between runs instead of an ephemeral/headless profile","If recently changed password or revoked sessions on Flomo, log in again to mint a new access_token"],"exampleFix":"// before (failing headless run with fresh profile)\n// cli command run with an empty browser profile\n\n// after (ensure a persistent, logged-in profile)\n// launch the browser with a persistent user-data dir and log in once:\n// browser.launch({ userDataDir: '/path/to/persistent-profile' })\n// then in the Flomo tab confirm:\n// JSON.parse(localStorage.getItem('me')).access_token !== undefined","handlingStrategy":"validation","validationCode":"// Run in the automation browser before invoking the command\nconst token = (() => {\n  try {\n    const me = JSON.parse(localStorage.getItem('me') || 'null');\n    return me?.access_token || me?.data?.access_token || '';\n  } catch { return ''; }\n})();\nif (typeof token !== 'string' || !token.trim()) {\n  throw new Error('No active Flomo session — sign in at https://v.flomoapp.com/ first');\n}","typeGuard":"function hasFlomoToken(me) {\n  const token = me?.access_token ?? me?.data?.access_token;\n  return typeof token === 'string' && token.trim().length > 0;\n}","tryCatchPattern":"try {\n  await runFlomoMemos();\n} catch (err) {\n  if (err instanceof AuthRequiredError) {\n    // open v.flomoapp.com, complete interactive sign-in, then retry once\n    await interactiveFlomoLogin();\n    await runFlomoMemos();\n  } else {\n    throw err;\n  }\n}","preventionTips":["Log in to Flomo in the automation browser before scripted runs","Use a persistent browser user-data dir so the session survives restarts","Re-login after password changes or Flomo session revocation","Periodically probe localStorage 'me' for a valid access_token before batch jobs"],"tags":["auth","session-expired","browser-automation","localstorage"],"backgroundTag":"missing-auth-session","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}