jackwener/OpenCLI · error · EmptyResultError

discord-app thread-read

Error message

discord-app thread-read

What it means

The 'discord-app thread-read' command throws EmptyResultError when reading messages from a Discord thread yields zero rows. After target-ownership validation passes, an empty message list is treated as a failed read because threads always have at least the originating message; emptiness means the thread content did not render. This prevents callers from silently getting an empty table on a broken scrape.

Source

Thrown at clis/discord-app/thread-read.js:37

    args: [
        { name: 'thread', required: false, help: 'Thread/post id, or a full Discord thread/post URL' },
        { name: 'count', required: false, default: '20', help: 'Number of messages to read (default: 20)' },
        { name: 'guild', required: false, help: 'Parent guild/server id or visible name' },
        { name: 'channel', required: false, help: 'Parent forum/channel id or visible name' },
        { name: 'url', required: false, help: 'Discord thread/post URL' },
    ],
    columns: ['Author', 'Time', 'Message', 'channel_id', 'message_id'],
    func: async (page, kwargs) => {
        const count = parsePositiveInt(kwargs.count, 20, 'count');
        const target = await resolveDiscordThreadTarget(page, kwargs);
        await navigateToDiscordTarget(page, target, { waitForContent: 'messages' });
        const rows = assertDiscordMessageRowsBelongToTarget(
            await readDiscordMessages(page, count),
            target,
            'Discord thread read',
        );
        if (rows.length === 0) {
            throw new EmptyResultError('discord-app thread-read', 'No messages were found in the selected Discord thread.');
        }
        return rows;
    },
});

export const __test__ = {
    threadReadCommand,
};

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the command with a longer --timeout so thread messages have time to render
  2. Open the thread URL in the automated browser and confirm messages are actually visible and the thread still exists
  3. Ensure the target channel contains an accessible (non-archived) thread
  4. If Discord changed its message DOM, update buildReadMessageScript/readDiscordMessages selectors in clis/discord-app/utils.js

Example fix

// before
await discordAppThreadRead(page, { url: threadUrl });
// after
await waitForDiscordContent(page, 'messages', { timeoutMs: 15000 });
await discordAppThreadRead(page, { url: threadUrl });
Defensive patterns

Strategy: validation

Validate before calling

function validateThreadTarget(url) {
  const m = url.match(/discord\.com\/channels\/(\d+)\/(\d+)\/(\d+)/(?:\?.*)?$/);
  if (!m) throw new Error('Provide a full thread URL: /channels/<guild>/<channel>/<thread>');
}

Type guard

function hasMessages(rows) {
  return Array.isArray(rows) && rows.length > 0;
}

Try / catch

try {
  const rows = await discordAppThreadRead(page, { url: threadUrl, count: 20 });
} catch (err) {
  if (String(err.message).includes('thread-read')) {
    console.error('Thread had no readable messages: confirm it exists, is not archived, and messages have rendered.');
  } else throw err;
}

Prevention

When it happens

Trigger: Running `discord-app thread-read` against a thread whose messages have not loaded in the browser (readDiscordMessages returned []), e.g. the thread view never finished loading, the thread was deleted/ inaccessible, or the read script executed before messages rendered.

Common situations: Pointing the command at an archived or deleted thread; slow network in CI so messages haven't hydrated; passing a thread URL while the app is stuck on a loading screen; Discord UI changes breaking the message DOM selectors.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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