jackwener/OpenCLI · error · CommandExecutionError
Flomo API returned HTTP ${resp.status}
Error message
Flomo API returned HTTP ${resp.status} What it means
fetchFlomoJson throws this CommandExecutionError when the Flomo API responds with any non-OK HTTP status other than 401/403 (e.g. 404, 429, 500, 502, 503). The CLI surfaces the bare status code so callers know the request reached the server but was rejected or failed server-side. 401/403 are deliberately excluded and raised as AuthRequiredError instead.
Source
Thrown at clis/flomo/memos.js:162
async function fetchFlomoJson(url, token) {
let resp;
try {
resp = await fetch(url, {
headers: {
Authorization: 'Bearer ' + token,
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
Accept: 'application/json',
},
});
} catch (err) {
throw new CommandExecutionError(`Failed to fetch Flomo memos: ${err instanceof Error ? err.message : String(err)}`);
}
if (resp.status === 401 || resp.status === 403) {
throw new AuthRequiredError(FLOMO_API_DOMAIN, `Flomo API returned HTTP ${resp.status}; please refresh your Flomo login session`);
}
if (!resp.ok) {
throw new CommandExecutionError(`Flomo API returned HTTP ${resp.status}`);
}
try {
return await resp.json();
} catch (err) {
throw new CommandExecutionError(`Flomo API returned malformed JSON: ${err instanceof Error ? err.message : String(err)}`);
}
}
async function readAccessToken(page) {
const token = unwrapBrowserResult(await page.evaluate(buildGetTokenJs()));
if (typeof token !== 'string' || !token.trim()) {
throw new AuthRequiredError(FLOMO_API_DOMAIN, 'Flomo memos requires an active signed-in Flomo browser session');
}
return token.trim();
}
const command = cli({
site: 'flomo',View on GitHub (pinned to 49907e53dc)
Solutions
- If status is 429, wait and back off before retrying — reduce call frequency.
- For 5xx, check Flomo's service status and retry later; it is a server-side issue.
- Ensure the CLI/opencli package is up to date in case the signed endpoint or parameters changed.
- Verify your system clock is accurate, since the request signature includes the current timestamp.
- For persistent non-transient statuses (e.g. 404), add retry-with-backoff only around 429/5xx and surface others directly.
Example fix
// before: no distinction between retryable and fatal statuses
await fetchFlomoJson(url, token);
// after: caller retries only transient statuses
const retry = [429, 500, 502, 503, 504];
for (let i = 0; ; i++) {
try { return await fetchFlomoJson(url, token); }
catch (e) {
const m = /HTTP (\d+)/.exec(e.message);
if (!m || !retry.includes(Number(m[1])) || i >= 3) throw e;
await new Promise((r) => setTimeout(r, 2 ** i * 1000));
}
} Defensive patterns
Strategy: retry
Validate before calling
// no caller-side check can prevent server-side statuses; optionally pre-check service health
const health = await fetch('https://flomoapp.com', { method: 'HEAD' }).then((r) => r.status).catch(() => 0);
if (health >= 500) console.warn('Flomo appears to be having server issues; expect HTTP 5xx'); Type guard
null
Try / catch
const RETRYABLE = new Set([429, 500, 502, 503, 504]);
try {
body = await fetchFlomoJson(url, token);
} catch (err) {
const m = /HTTP (\d+)/.exec(err.message || '');
if (m && RETRYABLE.has(Number(m[1]))) {
for (let i = 1; i <= 3; i++) {
await new Promise((r) => setTimeout(r, 2 ** i * 1000));
try { body = await fetchFlomoJson(url, token); break; } catch {}
}
}
if (!body) throw err;
} Prevention
- Throttle CLI invocations to avoid 429 rate limiting from Flomo.
- Retry only transient statuses (429/5xx) with exponential backoff; fail fast on 4xx.
- Keep the opencli package updated in case the signed endpoint/parameters change.
- Keep the system clock accurate — request signatures embed the current timestamp.
- Watch Flomo's service status before bulk runs.
When it happens
Trigger: Calling `flomo memos` during Flomo server incidents (5xx); rate limiting (429) from too-frequent calls; 404 if the /api/v1/memo/updated/ endpoint path or the pinned app_version 4.0 sign parameters become invalid; 400 from an invalid signature/timestamp combination.
Common situations: Hammering the CLI in a loop and hitting Flomo rate limits; Flomo outage or maintenance window; API version drift breaking the MD5-signed request parameters; misconfigured system clock producing bad `timestamp`/`sign` values.
Related errors
- coingecko categories returned HTTP ${resp.status}
- ${label} returned HTTP ${resp.status}
- Ctrip flight API returned HTTP ${status || 'unknown'}
- HTTP ${result.httpStatus} from /api/auth/session
- ${label} failed: HTTP ${response.status}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/b19952068f774fd8.
Report an issue: GitHub.