mastra-ai/mastra · warning

${flag} must be a positive integer

Error message

${flag} must be a positive integer

What it means

validate.positiveInt() parses a flag's raw string with Number() and requires the result to be an integer greater than 0, otherwise throwing '${flag} must be a positive integer'. Any non-numeric string, decimal, zero, or negative value fails at parse time.

Source

Thrown at mastracode/sdk/src/headless/flags.ts:35

export const VALID_OUTPUTS = ['human', 'json', 'jsonl'] as const;

/** Reusable validators. Each throws a descriptive Error or returns the typed value. */
const validate = {
  /** Restrict to a fixed set of string literals. */
  enum<T extends string>(flag: string, allowed: readonly T[]) {
    return (raw: string): T => {
      if (!(allowed as readonly string[]).includes(raw)) {
        throw new Error(`${flag} must be one of: ${allowed.join(', ')}`);
      }
      return raw as T;
    };
  },
  /** Require a positive (>0) integer. */
  positiveInt(flag: string) {
    return (raw: string): number => {
      const parsed = Number(raw);
      if (!Number.isInteger(parsed) || parsed <= 0) {
        throw new Error(`${flag} must be a positive integer`);
      }
      return parsed;
    };
  },
  /** Pass a string through unchanged. */
  string(raw: string): string {
    return raw;
  },
};

/**
 * One CLI flag. `key` is the long name (e.g. `output`); `field` is the
 * {@link import('./cli.js').HeadlessArgs} property it populates. `coerce`
 * converts the raw string and validates it. Boolean flags omit `coerce` and set
 * `field` to `true` when present.
 */
export interface FlagSpec {
  /** Long flag name without the leading `--`. */

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Provide an integer >= 1, e.g. --max-steps 5.
  2. Default unset numeric inputs before parsing: value ?? 1.
  3. Strip units/whitespace and parse with Number.parseInt in wrapper scripts before invoking the CLI.

Example fix

// before
mastracode --headless --max-turns 0 -p "run"
// after
mastracode --headless --max-turns 5 -p "run"
Defensive patterns

Strategy: validation

Validate before calling

const n = Number(raw);
if (!Number.isInteger(n) || n <= 0) {
  throw new Error(`${flag} must be a positive integer`);
}

Type guard

function isPositiveInt(v: unknown): v is number {
  return typeof v === 'number' && Number.isInteger(v) && v > 0;
}

Try / catch

try {
  parsed = parseFlag('max-turns', raw);
} catch (err) {
  if (err instanceof Error && err.message.includes('must be a positive integer')) {
    parsed = 1; // sane default
  } else { throw err; }
}

Prevention

When it happens

Trigger: Passing flags parsed by FLAGS with values like '0', '-1', '3.5', '', or 'many' to numeric options (counts, indices, timeouts) — Number(raw) either yields NaN, a non-integer, or <= 0.

Common situations: Users assuming 0 means 'unlimited'; off-by-one negatives from computed values; locale-formatted numbers or units ('1s', '50%'); empty flag values from shell variable expansion of unset variables.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/98fff31e73f3c661. Report an issue: GitHub.