{"record":{"id":"31c1cb5171178624","repo":"jackwener/OpenCLI","slug":"nowcoder-returned-mismatched-moment-feed-identity","errorCode":null,"errorMessage":"Nowcoder returned mismatched moment feed identity","messagePattern":"Nowcoder returned mismatched moment feed identity","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/nowcoder/posts.js","lineNumber":152,"sourceCode":"            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\nexport function projectNowcoderFeed(records, limit, source, wrapped = false) {\n    if (!Array.isArray(records)) throw new CommandExecutionError(`Nowcoder ${source} returned malformed records`);\n    const rows = [];\n    for (const record of records) {\n        const data = wrapped ? record?.data : record;","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/nowcoder/posts.js#L134-L170","documentation":"For moment-type feed rows, momentData.id (the entity id) must equal the outer row's contentId whenever the outer id is required or present. This error means the moment payload's entity id does not match the id the envelope advertised, so the row is treated as inconsistent and rejected.","triggerScenarios":"A contentType-74 row where (requireOuterId || data.contentId != null) and requiredId(momentData.id) !== requiredId(data.contentId) — inner entity id differs from outer contentId, or contentId is missing when required.","commonSituations":"Wrapped feed responses whose outer id refers to a different item (recommendation reshuffling); cached rows mixed from multiple requests; Nowcoder changing which identifier sits in contentId for moments (uuid vs entity id).","solutions":["Compare momentData.id with data.contentId on the offending row to determine the authoritative identifier.","Drop the forced outer-id requirement by not using wrapped mode or source='experience' if the API no longer guarantees it.","Pre-filter rows where momentData.id !== contentId before projection.","Update the identity check if Nowcoder changed the meaning of contentId for moments."],"exampleFix":"// before\nrows.push(projectFeedData(data, rows.length, source === 'experience' || wrapped));\n// after\nif (data?.contentId == null || String(data?.momentData?.id) === String(data.contentId)) {\n    rows.push(projectFeedData(data, rows.length, source === 'experience' || wrapped));\n}","handlingStrategy":"validation","validationCode":"const momentIdsMatch = (d) => d?.contentId == null || String(d?.momentData?.id) === String(d.contentId);\nconst usable = records.filter((r) => { const d = wrapped ? r?.data : r; return d?.contentType !== 74 || momentIdsMatch(d); });","typeGuard":"function hasConsistentMomentIdentity(d) { return isRecord(d) && (d.contentId == null || String(d.momentData?.id) === String(d.contentId)); }","tryCatchPattern":"try {\n    rows = projectNowcoderFeed(records, limit, source, wrapped);\n} catch (error) {\n    if (String(error.message).includes('mismatched moment feed identity')) {\n        rows = projectNowcoderFeed(records.filter((r) => hasConsistentMomentIdentity(wrapped ? r?.data : r)), limit, source, wrapped);\n    } else throw error;\n}","preventionTips":["Confirm which identifier Nowcoder places in contentId for moments (entity id vs uuid)","Pre-filter rows where momentData.id !== contentId","Avoid forcing wrapped mode unless the source guarantees outer ids","Never merge feed rows from multiple fetches"],"tags":["feed-parsing","data-integrity","id-mismatch"],"backgroundTag":"id-mismatch-between-envelope-and-payload","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}