jackwener/OpenCLI · error · CommandExecutionError

Flomo API returned a malformed memo entry

Error message

Flomo API returned a malformed memo entry

What it means

normalizeMemo validates each entry in the `data` array returned by the Flomo /memo/updated/ API before mapping it into CLI output rows. This error is thrown when an entry is not a plain object — it is null/undefined, a primitive, or an Array — meaning the upstream API response shape differs from what this CLI expects. It indicates an API contract change or an unexpected response body rather than a problem with the caller's arguments.

Source

Thrown at clis/flomo/memos.js:127

    .join(', ');
}

function normalizeImages(files) {
  if (!Array.isArray(files)) return '';
  return files
    .map((file) => file?.thumbnail_url || file?.url || '')
    .map((url) => String(url).trim())
    .filter(Boolean)
    .join(' | ');
}

function memoUrl(slug) {
  return slug ? `https://${FLOMO_APP_DOMAIN}/mine/?memo_id=${encodeURIComponent(slug)}` : '';
}

function normalizeMemo(memo) {
  if (!memo || typeof memo !== 'object' || Array.isArray(memo)) {
    throw new CommandExecutionError('Flomo API returned a malformed memo entry');
  }
  const slug = String(memo.slug || memo.id || '').trim();
  if (!slug) {
    throw new CommandExecutionError('Flomo API returned a memo without slug/id');
  }
  return {
    id: slug,
    url: memoUrl(slug),
    content: String(memo.content || '').trim(),
    slug,
    tags: normalizeTags(memo.tags),
    images: normalizeImages(memo.files),
    created_at: String(memo.created_at || ''),
    updated_at: String(memo.updated_at || ''),
  };
}

async function fetchFlomoJson(url, token) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Update the opencli package to the latest version so its Flomo parsing matches the current API schema.
  2. Retry after a short delay — a transient bad response (e.g. proxy injecting a page) usually does not persist.
  3. Check whether you are behind a proxy/firewall that rewrites responses to flomoapp.com and try a different network.
  4. Inspect the raw response by calling the signed URL manually to see what the API actually returns for memo entries.

Example fix

// before: CLI surfaces opaque CommandExecutionError
try {
  rows = body.data.map(normalizeMemo);
} catch (e) {
  console.error(e.message); // 'Flomo API returned a malformed memo entry'
}
// after: guard entries before mapping and report the offending index
const bad = body.data.findIndex((m) => !m || typeof m !== 'object' || Array.isArray(m));
if (bad !== -1) throw new Error(`memo at index ${bad} is not an object: ${JSON.stringify(body.data[bad])}`);
rows = body.data.map(normalizeMemo);
Defensive patterns

Strategy: validation

Validate before calling

function validateMemosResponse(body) {
  if (!body || typeof body !== 'object' || body.code !== 0) return 'bad envelope';
  if (!Array.isArray(body.data)) return 'data is not an array';
  const bad = body.data.findIndex((m) => !m || typeof m !== 'object' || Array.isArray(m));
  return bad === -1 ? null : `memo at index ${bad} is not an object`;
}
// call before mapping: const problem = validateMemosResponse(body);

Type guard

function isMemoEntry(m) {
  return m !== null && typeof m === 'object' && !Array.isArray(m);
}
const safeRows = body.data.filter(isMemoEntry).map(normalizeMemo);

Try / catch

try {
  rows = body.data.map(normalizeMemo);
} catch (err) {
  if (err.message.includes('malformed memo entry')) {
    console.error('Flomo response schema changed; update opencli and retry.');
  } else { throw err; }
}

Prevention

When it happens

Trigger: Calling `flomo memos` where body.data contains a null, undefined, string, number, or array element instead of a memo object; a Flomo API schema change that alters the memo list shape; a proxy/captive portal returning an unexpected JSON structure that still parses and has code 0 with non-object data items.

Common situations: Flomo changing their undocumented internal API response format; a middlebox or corporate proxy injecting its own JSON body; flomoapp.com rolling out a new app version (the CLI pins app_version 4.0) that reshapes memo entries; running an outdated CLI version against the current API.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/1975f09c87ef4821. Report an issue: GitHub.