{"record":{"id":"71387dd9633693a2","repo":"jackwener/OpenCLI","slug":"nowcoder-returned-mismatched-moment-feed-data","errorCode":null,"errorMessage":"Nowcoder returned mismatched moment feed data","messagePattern":"Nowcoder returned mismatched moment feed data","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/nowcoder/posts.js","lineNumber":147,"sourceCode":"            throw new CommandExecutionError('Nowcoder returned mismatched content feed data');\n        }\n        const post = data.contentData;\n        const id = requiredId(post.id, 'content id');\n        if ((requireOuterId || data.contentId != null) && id !== requiredId(data.contentId, 'content feed id')) {\n            throw new CommandExecutionError('Nowcoder returned mismatched content feed identity');\n        }\n        const uuid = requiredUuid(post.uuid, 'content uuid');\n        return {\n            ...commonFeedFields(data, post, 'content', post.authorId, post.createTime, index),\n            id,\n            uuid,\n            entity_id: requiredId(post.entityId, 'content entity id'),\n            url: `https://www.nowcoder.com/discuss/${id}`,\n        };\n    }\n    if (data.contentType === MOMENT_TYPE) {\n        if (!isRecord(data.momentData) || data.contentData != null) {\n            throw new CommandExecutionError('Nowcoder returned mismatched moment feed data');\n        }\n        const post = data.momentData;\n        const entityId = requiredId(post.id, 'moment entity id');\n        if ((requireOuterId || data.contentId != null) && entityId !== requiredId(data.contentId, 'moment feed id')) {\n            throw new CommandExecutionError('Nowcoder returned mismatched moment feed identity');\n        }\n        const uuid = requiredUuid(post.uuid, 'moment uuid');\n        return {\n            ...commonFeedFields(data, post, 'moment', post.userId, post.createdAt, index),\n            id: uuid,\n            uuid,\n            entity_id: entityId,\n            url: `https://www.nowcoder.com/feed/main/detail/${uuid}`,\n        };\n    }\n    throw new CommandExecutionError(`Nowcoder returned unsupported feed contentType ${String(data.contentType)}`);\n}\n","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/nowcoder/posts.js#L129-L165","documentation":"When a feed row declares contentType 74 (moment), projectFeedData requires momentData to be a record and contentData to be absent. This error means the row claims to be a moment but its payload shape says otherwise, so the library rejects it instead of projecting a broken moment post.","triggerScenarios":"A feed row with contentType===74 where momentData is null/not an object, or contentData is present alongside it.","commonSituations":"Deleted or restricted moments returning empty momentData while keeping the type marker; Nowcoder mixing content and moment payloads after a schema change; copy-pasted fixtures in tests with the wrong contentType; intermediate API versions returning both payloads.","solutions":["Inspect the row's momentData/contentData to confirm what Nowcoder actually returned for contentType 74.","Pre-filter rows missing valid momentData before calling projectNowcoderFeed.","If Nowcoder now sends both payloads, relax the projection guard to prefer momentData.","Re-fetch the feed in case the row was a transient partial response."],"exampleFix":"// before\nconst rows = projectNowcoderFeed(records, 10, 'recommend');\n// after\nconst valid = records.filter((r) => r?.data?.contentType !== 74 || r?.data?.momentData != null);\nconst rows = projectNowcoderFeed(valid, 10, 'recommend');","handlingStrategy":"validation","validationCode":"const isMomentRow = (d) => isRecord(d) && d.contentType === 74 && isRecord(d.momentData) && d.contentData == null;\nconst usable = records.filter((r) => { const d = wrapped ? r?.data : r; return d == null || isMomentRow(d) || d.contentType !== 74; });","typeGuard":"function isProjectableMomentRow(d) { return isRecord(d) && d.contentType === 74 && isRecord(d.momentData) && d.contentData == null; }","tryCatchPattern":"try {\n    rows = projectNowcoderFeed(records, limit, source, wrapped);\n} catch (error) {\n    if (String(error.message).includes('mismatched moment feed data')) {\n        console.error('Moment row payload missing or conflicting; inspect momentData');\n    }\n    throw error;\n}","preventionTips":["Verify MOMENT_TYPE (74) still matches the live API","Pre-filter rows with null momentData or stray contentData","Keep recorded API fixtures in tests to catch schema drift","Re-fetch on failure to rule out transient partial responses"],"tags":["feed-parsing","api-response","validation"],"backgroundTag":"api-response-schema-changed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}