{"record":{"id":"618c6d81d5ea387f","repo":"jackwener/OpenCLI","slug":"url-must-be-a-discord-channel-url-like-https-d","errorCode":null,"errorMessage":"--url must be a Discord channel URL like https://discord.com/channels/<guild_id>/<channel_id>.","messagePattern":"--url must be a Discord channel URL like https://discord\\.com/channels/<guild_id>/<channel_id>\\.","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/discord-app/utils.js","lineNumber":464,"sourceCode":"}\n\nfunction rowMatchesChannel(row, channel) {\n    if (!channel) return false;\n    if (String(row.channel_id || '') === channel) return true;\n    return normalizeDiscordName(row.Channel) === normalizeDiscordName(channel);\n}\n\nfunction rowMatchesGuild(row, guild) {\n    if (!guild) return true;\n    return String(row.guild_id || '') === guild || normalizeDiscordName(row.Server) === normalizeDiscordName(guild);\n}\n\nexport async function resolveDiscordChannelTarget(page, kwargs = {}, options = {}) {\n    const urlArg = stringArg(kwargs.url);\n    if (urlArg) {\n        const parsed = parseDiscordChannelUrl(urlArg);\n        if (!parsed || parsed.thread_id) {\n            throw new ArgumentError('--url must be a Discord channel URL like https://discord.com/channels/<guild_id>/<channel_id>.');\n        }\n        return parsed;\n    }\n\n    const guildArg = stringArg(kwargs.guild);\n    const channelArg = stringArg(kwargs.channel);\n    if (!guildArg && !channelArg) {\n        if (options.required) {\n            throw new ArgumentError('Pass --url or --guild/--channel to choose a Discord channel.');\n        }\n        return null;\n    }\n    if (!channelArg) {\n        throw new ArgumentError('Pass --channel with --guild, or use --url.');\n    }\n\n    let guildId = guildArg;\n    if (guildArg && !isDiscordSnowflake(guildArg) && guildArg !== '@me') {","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/discord-app/utils.js#L446-L482","documentation":"resolveDiscordChannelTarget validates the --url argument by running it through parseDiscordChannelUrl. It throws ArgumentError when the URL cannot be parsed at all or when the URL points at a thread (contains a thread_id), since this resolver only accepts plain channel URLs.","triggerScenarios":"Calling resolveDiscordChannelTarget (via the target/channelTarget commands) with kwargs.url set to a string that parseDiscordChannelUrl cannot parse (not matching https://discord.com/channels/<guild_id>/<channel_id>) or that parses with a thread_id (a 3-segment thread/post URL).","commonSituations":"Pasting a thread/message permalink instead of a channel URL; passing a bare channel name or id in --url; typos or missing the discord.com/channels prefix; copying a URL from a forum post or archived thread.","solutions":["Use a two-segment channel URL of the form https://discord.com/channels/<guild_id>/<channel_id>.","If you meant a thread/post, use resolveDiscordThreadTarget instead (or the thread-target command) which accepts the 3-segment URL.","Run \"opencli discord-app channels -f json\", copy the exact channel URL, and retry with --url.","Alternatively skip --url and pass --guild/--channel (numeric snowflake ids preferred)."],"exampleFix":"// before\nawait resolveDiscordChannelTarget(page, { url: 'https://discord.com/channels/123/456/789' }); // thread URL\n// after\nawait resolveDiscordChannelTarget(page, { url: 'https://discord.com/channels/123/456' }); // channel URL","handlingStrategy":"validation","validationCode":"function isChannelUrl(u) { const m = /^https:\\/\\/discord\\.com\\/channels\\/(\\d+)\\/(\\d+)$/.exec(String(u||'').trim()); return !!m && !m[3]; }\nif (!isChannelUrl(opts.url)) throw new Error('Expected a 2-segment Discord channel URL');","typeGuard":"function isDiscordChannelUrl(v) { return typeof v === 'string' && /^https:\\/\\/discord\\.com\\/channels\\/\\d+\\/\\d+$/.test(v.trim()); }","tryCatchPattern":"try { const target = await resolveDiscordChannelTarget(page, { url }); } catch (e) { if (String(e.message).includes('--url must be')) { /* fall back to --guild/--channel or fix URL */ } else throw e; }","preventionTips":["Copy channel URLs via Discord's right-click Copy Link on the channel, not the address bar while inside a thread.","Regex-check the URL has exactly two numeric segments before calling.","Use --guild/--channel numeric ids when the URL shape is uncertain."],"tags":["discord","cli","argument-validation","url-parsing"],"backgroundTag":"invalid-url-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}