{"record":{"id":"ab05d2d46be38a4c","repo":"jackwener/OpenCLI","slug":"label-returned-malformed-data","errorCode":null,"errorMessage":"${label} returned malformed data","messagePattern":"(.+?) returned malformed data","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/nowcoder/posts.js","lineNumber":259,"sourceCode":"        await page.goto('https://www.nowcoder.com');\n        payload = await page.fetchJson(url, options);\n    }\n    catch (error) {\n        const detail = String(error?.message ?? error);\n        if (/HTTP\\s+(401|403)|need login|not logged in/i.test(detail)) {\n            throw new AuthRequiredError('nowcoder.com', `${label} requires a logged-in Nowcoder session`);\n        }\n        throw new CommandExecutionError(`${label} failed: ${detail}`);\n    }\n    if (!isRecord(payload) || typeof payload.success !== 'boolean' || !Number.isSafeInteger(payload.code)) throw new CommandExecutionError(`${label} returned a malformed envelope`);\n    const message = typeof payload.msg === 'string' ? payload.msg : 'unknown error';\n    if (!payload.success || payload.code !== 0) {\n        if (payload.code === 999 || /need login|登录/i.test(message)) {\n            throw new AuthRequiredError('nowcoder.com', `${label} requires a logged-in Nowcoder session: ${message}`);\n        }\n        throw new CommandExecutionError(`${label} failed: ${message} (${payload.code})`);\n    }\n    if (!isRecord(payload.data)) throw new CommandExecutionError(`${label} returned malformed data`);\n    return payload.data;\n}\n","sourceCodeStart":241,"sourceCodeEnd":262,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/nowcoder/posts.js#L241-L262","documentation":"fetchNowcoderData requires payload.data to be a plain object (isRecord) even when success is true. If the Nowcoder API reports success but data is missing, null, or not an object, this CommandExecutionError is thrown. It guards downstream code from destructuring an undefined data field.","triggerScenarios":"A successful envelope ({ success:true, code:0 }) whose data field is null/undefined/an array/primitive — e.g. endpoints that return data:null when there are no results or when the API contract changed.","commonSituations":"Empty result sets where the API returns success:true with data:null; Nowcoder schema changes replacing the data object with something else; caching/CDN layers returning trimmed bodies.","solutions":["Check whether the query legitimately has no results and treat it as empty instead of an error","Re-run with different parameters (narrower query, smaller pageSize)","Verify the endpoint response shape with a raw request; if Nowcoder changed the schema, update the CLI parser","Wrap the call in try/catch and fall back to an empty result set when appropriate"],"exampleFix":"// before\nconst data = await fetchNowcoderData(page, url, opts);\nrender(data.list);\n// after\nlet data;\ntry { data = await fetchNowcoderData(page, url, opts); }\ncatch (e) { if (/malformed data/.test(e.message)) data = { list: [] }; else throw e; }\nrender(data.list);","handlingStrategy":"type-guard","validationCode":"function hasData(env){ return isEnvelope(env) && env.success === true && env.code === 0 && env.data !== null && typeof env.data === 'object' && !Array.isArray(env.data); }","typeGuard":"function isRecord(v){ return v !== null && typeof v === 'object' && !Array.isArray(v); }\nfunction hasPayloadData(env){ return isRecord(env) && isRecord(env.data); }","tryCatchPattern":"try { const data = await fetchNowcoderData(page, url, opts); }\ncatch (e) {\n  if (e instanceof CommandExecutionError && e.message.includes('malformed data')) return emptyResult;\n  throw e;\n}","preventionTips":["Check for empty result sets (data:null) before treating failures as bugs","Diff the endpoint response shape against expectations when Nowcoder ships changes","Wrap parsers with defensive optional chaining (d.data?.records)","Add a smoke test that asserts data is an object for each subcommand"],"tags":["schema","nowcoder","response-shape"],"backgroundTag":"response-schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}