{"record":{"id":"0fad6034e09fb9b8","repo":"jackwener/OpenCLI","slug":"parse-error-0fad60","errorCode":"PARSE_ERROR","errorMessage":"PARSE_ERROR","messagePattern":"PARSE_ERROR","errorType":"error_code","errorClass":"CliError","httpStatus":null,"severity":"error","filePath":"clis/xiaoyuzhou/transcript.js","lineNumber":38,"sourceCode":"    ],\n    columns: ['title', 'podcast', 'status', 'segments', 'json_file', 'text_file'],\n    func: async (kwargs) => {\n        if (kwargs.json === false && kwargs.text === false) {\n            throw new ArgumentError('At least one of --json or --text must be enabled', 'Example: opencli xiaoyuzhou transcript 69dd0c98e2c8be31551f6a33 --text true');\n        }\n        let credentials = loadXiaoyuzhouCredentials();\n        const episodeResponse = await requestXiaoyuzhouJson('/v1/episode/get', {\n            query: { eid: kwargs.id },\n            credentials,\n        });\n        credentials = episodeResponse.credentials;\n        const episode = episodeResponse.data;\n        if (!episode) {\n            throw new CliError('NOT_FOUND', 'Episode not found', 'Please check the episode ID');\n        }\n        const mediaId = String(episode.transcript?.mediaId || episode.media?.id || episode.transcriptMediaId || '').trim();\n        if (!mediaId) {\n            throw new CliError('PARSE_ERROR', 'mediaId not found in episode payload', 'Transcript metadata requires episode.transcript.mediaId, episode.media.id, or episode.transcriptMediaId');\n        }\n        const transcriptResponse = await requestXiaoyuzhouJson('/v1/episode-transcript/get', {\n            method: 'POST',\n            body: {\n                eid: kwargs.id,\n                mediaId,\n            },\n            credentials,\n        });\n        const transcriptMeta = transcriptResponse.data;\n        const transcriptUrl = String(transcriptMeta?.transcriptUrl || transcriptMeta?.url || '').trim();\n        if (!transcriptUrl) {\n            throw new CliError('EMPTY_RESULT', 'Transcript URL not found', 'This episode may not have transcript data available');\n        }\n        const transcriptBody = await fetchXiaoyuzhouTranscriptBody(transcriptUrl);\n        const { text, segmentCount } = extractTranscriptText(transcriptBody);\n        if (kwargs.text !== false && transcriptBody.trim() && !text.trim()) {\n            throw new CliError('PARSE_ERROR', 'Failed to extract transcript text', 'Transcript payload format is unsupported. Re-run with --json true to inspect the raw payload.');","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaoyuzhou/transcript.js#L20-L56","documentation":"The episode payload exists but contains no usable transcript media identifier. The CLI probes `episode.transcript.mediaId`, `episode.media.id`, and `episode.transcriptMediaId`; if all are missing/empty it throws CliError PARSE_ERROR listing the expected locations, since /v1/episode-transcript/get cannot be called without a mediaId.","triggerScenarios":"The episode has no transcript attached (mediaId absent in all three fallback fields), the API schema renamed these fields, or the episode payload is a partial/preview object without transcript metadata.","commonSituations":"Episodes published before the transcript feature, non-podcast audio items without transcripts, xiaoyuzhou schema changes after an app update, or fetching with reduced-auth tokens that receive redacted payloads.","solutions":["Confirm the episode actually has a transcript in the xiaoyuzhou app","Re-run after CLI update in case the schema extraction was fixed","Re-authenticate to rule out redacted payloads from bad credentials","If it's an old episode without transcripts, transcript retrieval is not possible for that eid"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"const ep = episodeResponse?.data;\nconst mediaId = String(ep?.transcript?.mediaId || ep?.media?.id || ep?.transcriptMediaId || '').trim();\nif (!mediaId) throw new Error('Episode has no transcript mediaId');","typeGuard":"const hasMediaId = (ep) => Boolean(ep && (ep.transcript?.mediaId || ep.media?.id || ep.transcriptMediaId));","tryCatchPattern":"try { await transcript(eid); } catch (e) { if (String(e).includes('mediaId not found')) { console.error('Episode lacks transcript metadata; skipping'); return null; } throw e; }","preventionTips":["Check the episode shows a transcript in the app first","Filter episode lists to transcript-enabled items","Update the CLI when xiaoyuzhou changes its schema","Log full episode payloads when mediaId extraction fails"],"tags":["cli","parse-error","missing-field","transcript"],"backgroundTag":"missing-required-field","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}