{"record":{"id":"a13ed844c25bd27c","repo":"jackwener/OpenCLI","slug":"weixin-search","errorCode":null,"errorMessage":"weixin search","messagePattern":"weixin search","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"info","filePath":"clis/weixin/search.js","lineNumber":134,"sourceCode":"        }\n        catch (error) {\n            const detail = error instanceof Error ? error.message : String(error);\n            throw new CommandExecutionError('weixin search failed while loading Sogou results', detail);\n        }\n\n        if (!payload || typeof payload !== 'object' || !Array.isArray(payload.rows)) {\n            throw new CommandExecutionError('weixin search returned an unreadable browser payload', 'Sogou Weixin may have changed its result page structure.');\n        }\n        if (payload.blocked) {\n            throw new CommandExecutionError('Sogou Weixin blocked this search request', 'Open weixin.sogou.com in Chrome and complete any verification before retrying.');\n        }\n        if (payload.invalidCount > 0) {\n            throw new CommandExecutionError('Sogou Weixin returned article cards without required title or URL', 'The result page structure may have changed; refusing to return a partial result set.');\n        }\n\n        const rows = payload.rows;\n        if (rows.length === 0 && payload.empty) {\n            throw new EmptyResultError('weixin search', 'Try a different keyword or a different page number.');\n        }\n        if (rows.length === 0) {\n            throw new CommandExecutionError('weixin search did not expose article result cards', 'Sogou Weixin may have changed its selectors or returned a transient shell page.');\n        }\n\n        return rows.slice(0, limit).map((row, index) => ({\n            rank: (pageNo - 1) * 10 + index + 1,\n            page: pageNo,\n            title: row.title,\n            url: row.url,\n            summary: row.summary,\n            publish_time: row.publish_time,\n        }));\n    },\n});\n\nexport const __test__ = {\n    MAX_LIMIT,","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/weixin/search.js#L116-L152","documentation":"This is an EmptyResultError with message 'weixin search' (the command name), thrown when the search genuinely completed but returned zero rows AND the payload was flagged empty. It means Sogou had no results for the keyword/page — not a failure of scraping or blocking. The remedy is to change the query or page.","triggerScenarios":"A keyword with no Weixin article matches; a page number beyond the available result count; very niche misspelled or overly specific queries.","commonSituations":"Searching long-tail or newly coined terms with no indexed articles; requesting page 5 of a keyword that only has 2 pages of results; automated pipelines iterating query lists that include dead keywords.","solutions":["Try a different or broader keyword","Use a lower page number (page 1) to confirm results exist for the term","Treat it as an expected empty state in batch pipelines and continue to the next keyword","Check spelling/synonyms of the query"],"exampleFix":"// before: assumes rows always\nconst rows = await search(q);\nconsole.log(rows[0].title);\n// after\nconst rows = await search(q).catch(e => isEmptyResult(e) ? [] : Promise.reject(e));\nif (!rows.length) console.log(`no weixin articles for: ${q}`);","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { rows = await weixinSearch(q); }\ncatch (e) { if (isEmptyResultError(e)) return []; throw e; }","preventionTips":["Treat EmptyResultError as expected in batch pipelines","Validate keywords exist before bulk runs","Start at page 1 when probing a new keyword"],"tags":["empty-result","scraping","expected-condition"],"backgroundTag":"empty-result-set","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}