{"record":{"id":"1820dfdd04e26ca5","repo":"jackwener/OpenCLI","slug":"failed-to-fetch-flomo-memos-err-instanceof-erro","errorCode":null,"errorMessage":"Failed to fetch Flomo memos: ${err instanceof Error ? err.message : String(err)}","messagePattern":"Failed to fetch Flomo memos: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/flomo/memos.js","lineNumber":156,"sourceCode":"    tags: normalizeTags(memo.tags),\n    images: normalizeImages(memo.files),\n    created_at: String(memo.created_at || ''),\n    updated_at: String(memo.updated_at || ''),\n  };\n}\n\nasync function fetchFlomoJson(url, token) {\n  let resp;\n  try {\n    resp = await fetch(url, {\n      headers: {\n        Authorization: 'Bearer ' + token,\n        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',\n        Accept: 'application/json',\n      },\n    });\n  } catch (err) {\n    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');","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/flomo/memos.js#L138-L174","documentation":"fetchFlomoJson wraps the low-level fetch to https://flomoapp.com/api/v1/memo/updated/. If fetch itself rejects — DNS failure, connection refused/reset, TLS error, timeout, or offline — this CommandExecutionError is thrown with the underlying error message embedded. It means the request never got an HTTP response, so it is a network-layer problem, not an API error.","triggerScenarios":"Calling `flomo memos` while offline; DNS resolution failure for flomoapp.com; TLS interception by a corporate proxy; connection reset/timeout; IPv6 connectivity issues; firewall blocking the outbound request from the headless browser host.","commonSituations":"Working on a VPN or corporate network that blocks or MITMs flomoapp.com; laptop asleep/network flapping during the CLI run; DNS misconfiguration; the browser session host having no internet access.","solutions":["Check basic connectivity (e.g. curl https://flomoapp.com) and retry the command.","Disable or reconfigure VPN/proxy that may block or intercept flomoapp.com traffic.","Verify DNS resolves flomoapp.com (try a public resolver like 1.1.1.1).","Increase any network timeouts or retry with exponential backoff for transient failures."],"exampleFix":"// before: single call, fails hard on transient network error\nconst body = await fetchFlomoJson(url, token);\n// after: retry transient network failures\nlet body;\nfor (let i = 0; i < 3; i++) {\n  try { body = await fetchFlomoJson(url, token); break; }\n  catch (e) {\n    if (i === 2 || /HTTP \\d+/.test(e.message)) throw e; // non-network errors don't retry\n    await new Promise((r) => setTimeout(r, 2 ** i * 500));\n  }\n}","handlingStrategy":"retry","validationCode":"// before calling the CLI, verify reachability of the API host\nconst ok = await fetch('https://flomoapp.com', { method: 'HEAD' })\n  .then(() => true)\n  .catch(() => false);\nif (!ok) throw new Error('flomoapp.com is unreachable; check network/VPN/DNS before running flomo memos');","typeGuard":"null","tryCatchPattern":"try {\n  body = await fetchFlomoJson(url, token);\n} catch (err) {\n  if (err.message.startsWith('Failed to fetch Flomo memos')) {\n    // network-layer failure: retry with backoff\n    for (let i = 1; i <= 3; i++) {\n      await new Promise((r) => setTimeout(r, i * 1000));\n      try { body = await fetchFlomoJson(url, token); break; } catch {}\n    }\n  }\n  if (!body) throw err;\n}","preventionTips":["Check connectivity/VPN/proxy settings before running CLI commands against flomoapp.com.","Wrap network calls in retry-with-exponential-backoff for transient failures.","Verify DNS resolution of flomoapp.com on hosts running automated sessions.","Avoid running the CLI immediately after system resume while the network is still settling."],"tags":["network","fetch-failed","dns","connectivity"],"backgroundTag":"connection-refused","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}