{"record":{"id":"9cc12f91a066a736","repo":"jackwener/OpenCLI","slug":"nowcoder-detail-returned-a-mismatched-post-entity","errorCode":null,"errorMessage":"Nowcoder detail returned a mismatched post entity type","messagePattern":"Nowcoder detail returned a mismatched post entity type","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/nowcoder/posts.js","lineNumber":205,"sourceCode":"        throw new ArgumentError('nowcoder detail requires a numeric content ID, moment UUID, or canonical Nowcoder URL');\n    }\n    const host = url.hostname.toLowerCase();\n    if (url.protocol !== 'https:' || url.username || url.password || url.port || url.hash\n        || (host !== 'nowcoder.com' && host !== 'www.nowcoder.com')) {\n        throw new ArgumentError('nowcoder detail only accepts canonical https://www.nowcoder.com post URLs');\n    }\n    const content = url.pathname.match(/^\\/discuss\\/([1-9]\\d*)\\/?$/);\n    if (content) return { post_type: 'content', value: content[1] };\n    const moment = url.pathname.match(/^\\/feed\\/main\\/detail\\/([0-9a-f]{32})\\/?$/i);\n    if (moment) return { post_type: 'moment', value: moment[1].toLowerCase() };\n    throw new ArgumentError('Unsupported Nowcoder URL; expected /discuss/<content-id> or /feed/main/detail/<moment-uuid>');\n}\n\nexport function projectNowcoderDetail(data, target) {\n    if (!isRecord(data) || !isRecord(data.frequencyData)) throw new CommandExecutionError('Nowcoder detail returned malformed post data');\n    const isContent = target.post_type === 'content';\n    const expectedEntityType = isContent ? CONTENT_ENTITY_TYPE : MOMENT_TYPE;\n    if (data.entityType !== expectedEntityType) throw new CommandExecutionError('Nowcoder detail returned a mismatched post entity type');\n    const uuid = requiredUuid(data.uuid, `${target.post_type} uuid`);\n    const entityId = requiredId(data.entityId, `${target.post_type} entity id`);\n    const id = isContent ? requiredId(data.id, 'content id') : uuid;\n    if (isContent ? id !== target.value : uuid !== target.value) throw new CommandExecutionError('Nowcoder detail returned a different post identity');\n    if (!isContent && entityId !== requiredId(data.id, 'moment id')) throw new CommandExecutionError('Nowcoder detail returned mismatched moment entity ids');\n    const expectedAuthorId = isContent ? data.authorId : data.userId;\n    const body = cleanBody(isContent ? data.richText : data.content, `${target.post_type} detail body`);\n    return {\n        post_type: target.post_type,\n        id,\n        uuid,\n        entity_id: entityId,\n        url: isContent\n            ? `https://www.nowcoder.com/discuss/${id}`\n            : `https://www.nowcoder.com/feed/main/detail/${uuid}`,\n        title: optionalText(data.title, `${target.post_type} title`) || '(untitled)',\n        ...authorFields(data.userBrief, expectedAuthorId, target.post_type),\n        content: body,","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/nowcoder/posts.js#L187-L223","documentation":"projectNowcoderDetail checks that data.entityType matches the type expected from the parsed target: the content entity type for /discuss/<id> targets, or the moment type for /feed/main/detail/<uuid> targets. If the API returns an entity of a different type (e.g. you passed a discuss ID but the API resolved to a different entity kind), this CommandExecutionError is thrown to prevent projecting data under the wrong shape.","triggerScenarios":"Fetching a detail where the numeric /discuss/<id> actually resolves to a non-content entityType in the API response, or a feed moment UUID resolves to a non-moment entityType; passing a moment UUID via the /discuss/ route or vice versa.","commonSituations":"Confusing content IDs with moment IDs; a URL pointing to a nowcoder entity type the CLI does not support (e.g. a comment or course item) that shares the same route shape; Nowcoder repurposing entity types in API updates.","solutions":["Confirm the URL/ID is really a discuss post (www.nowcoder.com/discuss/<id>) or a feed moment (/feed/main/detail/<uuid>) and not another entity type.","Fetch the target directly by its canonical ID/UUID rather than a URL of the wrong kind.","If the API legitimately changed entityType values, update the CONTENT_ENTITY_TYPE / MOMENT_TYPE constants in the library."],"exampleFix":"// before\nnowcoder detail \"https://www.nowcoder.com/feed/main/detail/abc123\"  // uuid passed via wrong route/shape\n// after\nnowcoder detail \"https://www.nowcoder.com/discuss/70123456\"  // content post via content route","handlingStrategy":"validation","validationCode":"// before calling, ensure the target kind matches the route kind\nfunction targetKindMatches(value) {\n  if (/^\\/discuss\\/\\d+/.test(value)) return 'content';\n  if (/^\\/feed\\/main\\/detail\\/[0-9a-f]{32}$/i.test(value)) return 'moment';\n  return /^[0-9a-f]{32}$/i.test(value) ? 'moment' : 'content';\n}","typeGuard":"function isMomentTarget(target) {\n  return target !== null && typeof target === 'object' && target.post_type === 'moment'\n    && typeof target.value === 'string' && /^[0-9a-f]{32}$/.test(target.value);\n}","tryCatchPattern":"try {\n  const post = await nowcoderDetail(target);\n} catch (err) {\n  if (err instanceof CommandExecutionError && /mismatched post entity type/.test(err.message)) {\n    console.error('The ID/UUID does not identify the expected entity kind; re-check the source URL.');\n  } else throw err;\n}","preventionTips":["Never pass a moment UUID through a /discuss/ URL or a content ID through a /feed/ URL.","Keep content IDs (numeric) and moment UUIDs (32 hex chars) in separate variables/fields.","Verify the entity type by opening the URL in a browser before automation."],"tags":["api-response","type-mismatch","schema-validation"],"backgroundTag":"api-response-type-mismatch","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}