jackwener/OpenCLI · error · EmptyResultError

Photo ID ${requestedPhotoId} was not found under subject ${s

Error message

Photo ID ${requestedPhotoId} was not found under subject ${subjectId}. Try "douban photos ${subjectId} -f json" first.

What it means

In the douban download command, when a specific photo id is requested the fetched photo list is filtered by photoId; if nothing matches, EmptyResultError is thrown because there is nothing to download. The message hints at listing photos as JSON first to discover valid ids.

Source

Thrown at clis/douban/download.js:44

    ],
    columns: ['index', 'title', 'status', 'size'],
    func: async (page, kwargs) => {
        const subjectId = normalizeDoubanSubjectId(String(kwargs.id || ''));
        const output = String(kwargs.output || './douban-downloads');
        const requestedPhotoId = String(kwargs['photo-id'] || '').trim();
        const loadOptions = {
            type: String(kwargs.type || 'Rb'),
        };
        if (requestedPhotoId)
            loadOptions.targetPhotoId = requestedPhotoId;
        else
            loadOptions.limit = Number(kwargs.limit) || 120;
        const data = await loadDoubanSubjectPhotos(page, subjectId, loadOptions);
        const photos = requestedPhotoId
            ? data.photos.filter((photo) => photo.photoId === requestedPhotoId)
            : data.photos;
        if (requestedPhotoId && !photos.length) {
            throw new EmptyResultError('douban download', `Photo ID ${requestedPhotoId} was not found under subject ${subjectId}. Try "douban photos ${subjectId} -f json" first.`);
        }
        const outputDir = path.join(output, subjectId);
        fs.mkdirSync(outputDir, { recursive: true });
        const results = [];
        for (const photo of photos) {
            const filename = buildDoubanPhotoFilename(subjectId, photo);
            const destPath = path.join(outputDir, filename);
            const result = await httpDownload(photo.imageUrl, destPath, {
                headers: { Referer: photo.detailUrl || `https://movie.douban.com/subject/${subjectId}/photos?type=${encodeURIComponent(String(kwargs.type || 'Rb'))}` },
                timeout: 60000,
            });
            results.push({
                index: photo.index,
                title: photo.title,
                photo_id: photo.photoId,
                image_url: photo.imageUrl,
                detail_url: photo.detailUrl,
                status: result.success ? 'success' : 'failed',

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Run "douban photos <subjectId> -f json" and pick a photoId that actually exists
  2. Increase the load limit or paginate further if the photo may be beyond the fetched set
  3. Confirm the photo belongs to the given subject and has not been deleted

Example fix

// before
douban download 1234567 --photo 99999999
// after
douban photos 1234567 -f json   # find valid photoId
douban download 1234567 --photo <validId>
Defensive patterns

Strategy: fallback

Validate before calling

const listing = await doubanPhotos(subjectId, { format: 'json' });
const valid = listing.photos.some(p => p.photoId === requestedPhotoId);
if (!valid) console.error(`Photo ${requestedPhotoId} not in subject ${subjectId}; pick from -f json output`);

Type guard

function photoExists(photos, id) { return photos.some(p => p.photoId === id); }

Try / catch

try { await doubanDownload(subjectId, { photo: requestedPhotoId }); } catch (e) { if (e instanceof EmptyResultError) { const all = await doubanPhotos(subjectId, { format: 'json' }); /* pick a valid photoId */ } else throw e; }

Prevention

When it happens

Trigger: Typo in the photo id; the photo belongs to a different subject; the photo was deleted; the load only fetched the first page(s) (default limit 120) so an older photo beyond the fetched window is absent from data.photos.

Common situations: Hardcoded/stale photo ids from an earlier run; pagination limits hiding older photos; confusing photo ids across two similar subjects.

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


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/48280ca04f9065a6. Report an issue: GitHub.