jackwener/OpenCLI · error · ArgumentError

--${label} must be a positive integer.

Error message

--${label} must be a positive integer.

What it means

parsePositiveInt validates numeric CLI options (timeout, count, limit). Values that are not pure digit strings fail the /^\d+$/ test and throw ArgumentError '--<label> must be a positive integer.' The first throw site handles non-numeric input; undefined/null/empty string fall back to the default instead of throwing.

Source

Thrown at clis/discord-app/utils.js:104

        channel_id: channelId,
        ...(threadId ? { thread_id: threadId } : {}),
        url: buildDiscordChannelUrl({ guildId, channelId, threadId }),
    };
}

export function buildDiscordChannelUrl({ guildId, channelId, threadId }) {
    if (!guildId || !channelId) {
        throw new ArgumentError('Discord channel navigation requires both guild_id and channel_id.');
    }
    const base = `${DISCORD_ORIGIN}/channels/${encodeURIComponent(String(guildId))}/${encodeURIComponent(String(channelId))}`;
    return threadId ? `${base}/${encodeURIComponent(String(threadId))}` : base;
}

export function parsePositiveInt(value, fallback, label) {
    if (value === undefined || value === null || value === '') return fallback;
    const raw = String(value).trim();
    if (!/^\d+$/.test(raw)) {
        throw new ArgumentError(`--${label} must be a positive integer.`);
    }
    const parsed = parseInt(raw, 10);
    if (!Number.isFinite(parsed) || parsed <= 0) {
        throw new ArgumentError(`--${label} must be a positive integer.`);
    }
    return parsed;
}

export function hasDiscordChannelTarget(kwargs = {}) {
    return Boolean(stringArg(kwargs.url) || stringArg(kwargs.guild) || stringArg(kwargs.channel));
}

export function buildListChannelsScript() {
    return `
      (function __opencliDiscordListChannels() {
        function parseRoute(raw) {
          try {
            var url = new URL(raw, 'https://discord.com');

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass only bare positive integer digits, e.g. --limit 30, --count 20
  2. Quote shell variables and validate numeric input before interpolating into flags
  3. Strip units/formatting in your wrapper script (parse '30s' to 30) before invoking the CLI
  4. Omit the flag entirely to use the built-in default

Example fix

// before
spawn('discord-app', ['threads', '--limit', limit || 'all'])
// after
const n = Number.parseInt(limit, 10);
if (!Number.isInteger(n) || n <= 0) throw new Error('limit must be a positive integer');
spawn('discord-app', ['threads', '--limit', String(n)])
Defensive patterns

Strategy: validation

Validate before calling

function toPositiveInt(value, label) {
  const raw = String(value ?? '').trim();
  if (!/^\d+$/.test(raw) || parseInt(raw, 10) <= 0) {
    throw new Error(`--${label} must be a positive integer`);
  }
  return parseInt(raw, 10);
}

Type guard

function isPositiveInt(v) {
  return typeof v === 'number' ? Number.isInteger(v) && v > 0 : /^\d+$/.test(String(v).trim());
}

Try / catch

try {
  await discordAppThreads(page, { limit: rawLimit });
} catch (err) {
  if (String(err.message).includes('must be a positive integer')) {
    console.error(`--limit got '${rawLimit}': pass bare digits like --limit 30.`);
  } else throw err;
}

Prevention

When it happens

Trigger: Passing --limit abc, --count '10x', a negative like --limit -5, or a float like --count 2.5 to commands such as `discord-app threads --limit`, `discord-app thread-read --count`, or timeout flags.

Common situations: Copy-pasting values with units ('30s', '5m'); shells expanding values oddly; scripting with unquoted variables that inject multiple words; locale-formatted numbers with separators ('1,000').

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


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