{"record":{"id":"237b4f00d18454cf","repo":"jackwener/OpenCLI","slug":"nowcoder-returned-a-malformed-label","errorCode":null,"errorMessage":"Nowcoder returned a malformed ${label}","messagePattern":"Nowcoder returned a malformed (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/nowcoder/posts.js","lineNumber":21,"sourceCode":"    AuthRequiredError,\n    CommandExecutionError,\n    EmptyResultError,\n} from '@jackwener/opencli/errors';\n\nconst CONTENT_FEED_TYPE = 250;\nconst CONTENT_ENTITY_TYPE = 8;\nconst MOMENT_TYPE = 74;\nconst UUID_PATTERN = /^[0-9a-f]{32}$/i;\nconst NUMERIC_ID_PATTERN = /^[1-9]\\d*$/;\nconst NAMED_ENTITIES = { nbsp: ' ', amp: '&', lt: '<', gt: '>', quot: '\"', apos: \"'\" };\n\nfunction isRecord(value) {\n    return Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction requiredId(value, label) {\n    const id = typeof value === 'number' && Number.isSafeInteger(value) ? String(value) : value;\n    if (typeof id !== 'string' || !NUMERIC_ID_PATTERN.test(id)) throw new CommandExecutionError(`Nowcoder returned a malformed ${label}`);\n    return id;\n}\n\nfunction requiredUuid(value, label) {\n    if (typeof value !== 'string' || !UUID_PATTERN.test(value)) throw new CommandExecutionError(`Nowcoder returned a malformed ${label}`);\n    return value.toLowerCase();\n}\n\nfunction optionalText(value, label) {\n    if (value == null) return '';\n    if (typeof value !== 'string') throw new CommandExecutionError(`Nowcoder returned a malformed ${label}`);\n    return value.trim();\n}\n\nfunction decodeEntities(value) {\n    return value.replace(/&(#x[0-9a-f]+|#\\d+|nbsp|amp|lt|gt|quot|apos);/gi, (match, entity) => {\n        const normalized = entity.toLowerCase();\n        if (NAMED_ENTITIES[normalized] != null) return NAMED_ENTITIES[normalized];","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/nowcoder/posts.js#L3-L39","documentation":"This library validates every identifier that comes back from Nowcoder API payloads before exposing it. requiredId() accepts either a safe integer or a numeric string matching /^[1-9]\\d*$/, and throws CommandExecutionError('Nowcoder returned a malformed <label>') when the value is anything else (missing, null, an object, a non-numeric or zero-padded string). It signals that Nowcoder returned data whose shape the library does not recognize, so the raw value is never propagated.","triggerScenarios":"A feed or detail response row has userBrief.userId, contentData.id/contentId/entityId, or momentData.id/contentId that is undefined, null, 0, a negative number, a float, a non-numeric string, or an object — e.g. Nowcoder changed its API field names, returned an error/empty item inside a list, or a wrapped record was unwrapped incorrectly. Called from authorId/authorFields/id/projectFeedData/entityId/projectNowcoderDetail paths.","commonSituations":"Nowcoder silently changes its JSON schema (field renamed from userId, id now a string with a prefix); an item in the feed list is a stub/ad payload without ids; scraping without login returns degraded payloads; a moment post's id field is absent for deleted content; using an unofficial/outdated endpoint that no longer matches the expected shape.","solutions":["Inspect the raw HTTP payload for the item whose <label> is cited (e.g. 'content id', 'userBrief.userId') and confirm the field is a positive integer or numeric string","Update the library or fix the endpoint URL — the API schema likely changed","Ensure the Nowcoder session is valid (log in); degraded/unauthenticated payloads often lack proper id fields","Pre-filter feed records, dropping items that lack the expected id fields before calling the projection functions"],"exampleFix":"// before (raw value passed straight through)\nconst id = post.id;\n// after (pre-validate in caller code)\nconst id = /^[1-9]\\d*$/.test(String(post.id)) ? String(post.id) : null;\nif (id == null) continue; // skip malformed feed item","handlingStrategy":"validation","validationCode":"function isValidNowcoderId(v) {\n  const s = typeof v === 'number' && Number.isSafeInteger(v) ? String(v) : v;\n  return typeof s === 'string' && /^[1-9]\\d*$/.test(s);\n}\n// run before processing: records.every(r => isValidNowcoderId(r.data?.contentData?.id))","typeGuard":"function isNowcoderId(value) {\n  const id = typeof value === 'number' && Number.isSafeInteger(value) ? String(value) : value;\n  return typeof id === 'string' && /^[1-9]\\d*$/.test(id);\n}","tryCatchPattern":"try {\n  const rows = projectNowcoderFeed(records, limit, source, wrapped);\n} catch (err) {\n  if (err instanceof CommandExecutionError && /malformed/.test(err.message)) {\n    console.warn('Skipping malformed Nowcoder payload:', err.message);\n    // re-fetch or skip the offending record\n  } else throw err;\n}","preventionTips":["Validate id fields with a regex/number check before feeding records into the projection functions","Keep the library updated against Nowcoder API schema changes","Use a valid logged-in session so payloads are not degraded","Pre-filter feed arrays, dropping stub/ad rows without ids"],"tags":["nowcoder","api-schema","validation","scraping"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}