jackwener/OpenCLI · error · CommandExecutionError

Zhihu user articles returned malformed row identity

Error message

Zhihu user articles returned malformed row identity

What it means

After fetching a Zhihu user's article list from the members/<slug>/articles API, each row is validated: an item without both id and title indicates the API returned rows this CLI cannot identify, so it throws CommandExecutionError('Zhihu user articles returned malformed row identity') rather than emitting a garbage row.

Source

Thrown at clis/zhihu/user-articles.js:28

    name: 'user-articles',
    access: 'read',
    description: '知乎某用户的文章/专栏列表',
    domain: 'www.zhihu.com',
    strategy: Strategy.COOKIE,
    args: [
        { name: 'user', type: 'string', required: true, positional: true, help: 'User url_token or people URL' },
        { name: 'limit', type: 'int', default: 20, help: 'Number of articles to return (max 1000)' },
    ],
    columns: ['rank', 'title', 'votes', 'comments', 'created', 'url'],
    func: async (page, kwargs) => {
        const slug = parseZhihuUser(kwargs.user);
        const limit = validateLimit(kwargs.limit);
        await page.goto('https://www.zhihu.com');
        const first = `https://www.zhihu.com/api/v4/members/${encodeURIComponent(slug)}/articles?limit=20&offset=0&include=${encodeURIComponent(INCLUDE)}`;
        const items = await fetchZhihuList(page, first, limit, 'user articles');
        return items.map((a, i) => {
            if (!a.id || !a.title) {
                throw new CommandExecutionError('Zhihu user articles returned malformed row identity');
            }
            return {
                rank: i + 1,
                title: String(a.title || ''),
                votes: a.voteup_count ?? 0,
                comments: a.comment_count ?? 0,
                created: a.created ?? a.updated ?? 0,
                url: `https://zhuanlan.zhihu.com/p/${a.id}`,
            };
        });
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Rerun the command; transient/anti-bot responses often resolve on retry
  2. Lower --limit so fewer rows are fetched per page
  3. Verify the user slug is correct (a wrong slug can return odd payloads)
  4. Update the CLI/library to a version matching the current Zhihu API shape
Defensive patterns

Strategy: try-catch

Validate before calling

function looksLikeArticleRow(a) { return a && typeof a === 'object' && (a.id !== undefined && a.id !== null) && (typeof a.title === 'string' && a.title.length > 0); }
// precheck after fetch, before mapping
if (Array.isArray(items) && items.length && !items.every(looksLikeArticleRow)) { /* retry or bail */ }

Type guard

const hasRowIdentity = (a) => typeof a === 'object' && a !== null && 'id' in a && typeof a.title === 'string' && a.title.length > 0;

Try / catch

try {
  const articles = await getUserArticles(slug, limit);
} catch (e) {
  if (e.message.includes('malformed row identity')) {
    await sleep(2000); // backoff and retry once; else surface API-shape issue
  } else throw e;
}

Prevention

When it happens

Trigger: Running the user-articles command when Zhihu's v4 articles API returns items lacking id or title — e.g. an API shape change, protected/deleted articles rendered as stubs, anti-scraping interstitials, or partial/limit-offset responses returning placeholder objects.

Common situations: Zhihu deploying a new API response shape; anonymous scraping sessions getting degraded data; include= projection returning fewer fields than expected; pagination windows hitting hidden articles.

Understand the failure class

Related errors


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