jackwener/OpenCLI · error · CliError
NOT_FOUND
NOT_FOUND
Error message
Episode not found
What it means
Thrown by the Xiaoyuzhou episode info command (clis/xiaoyuzhou/episode.js:23) as a CliError with code NOT_FOUND when /v1/episode/get returns successfully but response.data is falsy. Same root cause as error 4902 but in the metadata/info code path: the library cannot display details for an episode the API does not return.
Source
Thrown at clis/xiaoyuzhou/episode.js:23
cli({
site: 'xiaoyuzhou',
name: 'episode',
access: 'read',
description: 'View details of a Xiaoyuzhou podcast episode',
domain: 'www.xiaoyuzhoufm.com',
strategy: Strategy.LOCAL,
browser: false,
args: [{ name: 'id', positional: true, required: true, help: 'Episode ID (eid from podcast-episodes output)' }],
columns: ['title', 'podcast', 'duration', 'plays', 'comments', 'likes', 'date'],
func: async (args) => {
const credentials = loadXiaoyuzhouCredentials();
const response = await requestXiaoyuzhouJson('/v1/episode/get', {
query: { eid: args.id },
credentials,
});
const ep = response.data;
if (!ep)
throw new CliError('NOT_FOUND', 'Episode not found', 'Please check the ID');
return [{
title: ep.title,
podcast: ep.podcast?.title,
duration: formatDuration(ep.duration),
plays: ep.playCount,
comments: ep.commentCount,
likes: ep.clapCount,
date: formatDate(ep.pubDate),
}];
},
});
View on GitHub (pinned to 49907e53dc)
Solutions
- Verify the episode ID against the episode's share URL (segment after /episode/)
- Ensure you are passing an episode ID, not a podcast (pid) or user ID
- Refresh credentials and retry in case an expired token is causing empty data
- If the episode was deleted or is access-restricted, it cannot be fetched — choose another episode
Example fix
// before
await cli.episode({ id: '62d0f3ea' }); // truncated
// after
await cli.episode({ id: '62d0f3ea9a1f2b1a3c4d5e6f' }); // full ID from episode URL Defensive patterns
Strategy: validation
Validate before calling
function isValidEpisodeId(id) {
return typeof id === 'string' && /^[0-9a-f]{24}$/.test(id);
}
if (!isValidEpisodeId(args.id)) throw new Error('Provide the full 24-char episode ID from the episode share URL'); Type guard
function hasEpisodeData(res) {
return res != null && typeof res === 'object' && res.data != null && typeof res.data === 'object';
} Try / catch
try {
const info = await cli.episode({ id });
} catch (error) {
if (error.code === 'NOT_FOUND') {
console.error(`No episode found for ${id} — check the ID (eid, not pid) and that the episode still exists`);
} else throw error;
} Prevention
- Copy episode IDs from the /episode/ path of share URLs rather than typing them
- Confirm you are passing an episode ID, not a podcast or user ID
- Refresh credentials if many IDs suddenly return empty data
- Handle deleted/private episodes gracefully in batch scripts
When it happens
Trigger: Running the xiaoyuzhou episode command with an --id the API cannot resolve: nonexistent, deleted, private, or mistyped episode ID, or credentials whose token scope excludes the episode so data comes back empty.
Common situations: Typos when hand-typing the 24-char episode ID; referencing an episode from a podcast that removed it; expired auth token silently yielding empty data instead of an auth error; passing a podcast ID where an episode ID is expected.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- NOT_FOUND
- archive item returned malformed payload: files must be an ar
- archive search failed: HTTP ${resp.status}
- archive search returned malformed payload: response.docs mus
- No sidebar conversation matched "${raw}". Try the exact id f
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/af91cc50679e8e1f.
Report an issue: GitHub.