{"record":{"id":"4875fa3f47fc08e6","repo":"jackwener/OpenCLI","slug":"suno-feed-lookup-returned-malformed-clips-payload-4875fa","errorCode":null,"errorMessage":"Suno feed lookup returned malformed clips payload","messagePattern":"Suno feed lookup returned malformed clips payload","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/suno/list.js","lineNumber":59,"sourceCode":"            const browserToken = JSON.stringify({ token: btoa(JSON.stringify({ timestamp: Date.now() })) });\n            const res = await fetch('${STUDIO_API}/api/feed/v2?page=${pageOffset}', {\n                headers: {\n                    'Authorization': 'Bearer ' + (await window.Clerk.session.getToken()),\n                    'browser-token': browserToken,\n                    'device-id': ${JSON.stringify(deviceId)},\n                },\n            });\n            if (!res.ok) return { ok: false, status: res.status };\n            const data = await res.json().catch(() => null);\n            if (!data || !Array.isArray(data.clips)) return { ok: false, error: 'malformed clips payload' };\n            return { ok: true, clips: data.clips };\n        })()`));\n\n        if (!result?.ok) {\n            throw new CommandExecutionError(result?.error || `Suno feed lookup failed (HTTP ${result?.status || '?'}).`);\n        }\n        if (!Array.isArray(result.clips)) {\n            throw new CommandExecutionError('Suno feed lookup returned malformed clips payload');\n        }\n        if (result.clips.length === 0) {\n            throw new EmptyResultError('suno list', 'No Suno clips found in your library.');\n        }\n\n        return result.clips.slice(0, limit).map((c, i) => {\n            if (!c || typeof c.id !== 'string' || !c.id) {\n                throw new CommandExecutionError('Suno feed lookup returned malformed clip identity');\n            }\n            return {\n                rank: i + 1 + pageOffset * limit,\n                clip: c.id.slice(0, 8),\n                title: c.title || '(untitled)',\n                status: c.status || '?',\n                created: (c.created_at || '').replace('T', ' ').replace(/\\..*$/, '').replace(/Z$/, ''),\n                link: `${SUNO_URL}/song/${c.id}`,\n            };\n        });","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/suno/list.js#L41-L77","documentation":"A defensive second check: even when the feed fetch reports ok, the CLI re-validates that `result.clips` is an array before slicing/mapping. It throws if the payload shape is unusable.","triggerScenarios":"`result.ok === true` but `result.clips` is not an array — practically unreachable via the in-page evaluate (which already validates), but guards against unwrapEvaluateResult returning an unexpected shape.","commonSituations":"Tooling/hydration mismatch where unwrapEvaluateResult returns a non-standard object, or future refactors that bypass the in-page shape check.","solutions":["Log the raw evaluate result from unwrapEvaluateResult to see the actual shape.","Check for opencli/Suno schema drift and update the parsing code.","Retry the command — if intermittent, it may be a serialization hiccup in the page bridge."],"exampleFix":"// before: blind trust\nconst first = result.clips[0];\n// after\nif (!Array.isArray(result.clips)) throw new Error('unexpected feed payload: ' + JSON.stringify(result));\nconst first = result.clips[0];","handlingStrategy":"type-guard","validationCode":"const result = unwrapEvaluateResult(await page.evaluate(feedScript));\nif (!result || typeof result !== 'object') throw new Error('feed bridge returned non-object');","typeGuard":"function isFeedResultOk(r) { return !!r && r.ok === true && Array.isArray(r.clips); }","tryCatchPattern":"try {\n  const clips = await listSunoClips();\n} catch (e) {\n  if (/malformed clips payload/.test(e.message)) {\n    logRawBridgeResultForDebugging();\n    throw new Error('Suno feed schema drift or page-bridge issue — inspect raw payload');\n  }\n  throw e;\n}","preventionTips":["Keep the in-page shape check and the post-unwrap check in sync after refactors.","Log raw evaluate results on any payload anomaly.","Add unit tests covering unwrapEvaluateResult edge cases (null, string, nested ok).","Re-run the command once before deep debugging — serialization hiccups can be transient."],"tags":["schema-validation","api-contract","defensive-check"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}