jackwener/OpenCLI · error · ArgumentError

steam currency must be a two-letter storefront country code

Error message

steam currency must be a two-letter storefront country code (got "${value}")

What it means

requireCountryCode validates the storefront country code controlling Steam regional pricing; it must be exactly two ASCII letters after trimming/lowercasing. Invalid codes throw ArgumentError with the offending value and examples.

Source

Thrown at clis/steam/utils.js:20

// endpoints (no browser).
import { ArgumentError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';

export const STEAM_STORE = 'https://store.steampowered.com';
const UA = 'opencli-steam-adapter (+https://github.com/jackwener/opencli)';

export function requireString(value, label) {
    const s = String(value ?? '').trim();
    if (!s) {
        throw new ArgumentError(`steam ${label} cannot be empty`);
    }
    return s;
}

export function requireCountryCode(value, defaultValue = 'us') {
    const raw = value === undefined || value === null ? defaultValue : value;
    const code = String(raw).trim().toLowerCase();
    if (!/^[a-z]{2}$/.test(code)) {
        throw new ArgumentError(
            `steam currency must be a two-letter storefront country code (got "${value}")`,
            'Examples: us, cn, jp, de. This controls Steam regional pricing and availability.',
        );
    }
    return code;
}

export function requireBoundedInt(value, defaultValue, maxValue, label = 'limit') {
    const raw = value ?? defaultValue;
    const n = typeof raw === 'number' ? raw : Number(raw);
    if (!Number.isInteger(n) || n <= 0) {
        throw new ArgumentError(`steam ${label} must be a positive integer`);
    }
    if (n > maxValue) {
        throw new ArgumentError(`steam ${label} must be <= ${maxValue}`);
    }
    return n;
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a two-letter ISO 3166-1 alpha-2 code, e.g. us, cn, jp, de
  2. Lowercase/trim inputs at the call site before passing
  3. Replace locale strings like en-US with just the country portion (us)
  4. Catch ArgumentError and show the examples included in the error's hint

Example fix

// before
const cc = args.currency; // "USA"
// after
const cc = requireCountryCode(String(args.currency ?? 'us').slice(0, 2).toLowerCase());
Defensive patterns

Strategy: validation

Validate before calling

const CC_RE = /^[a-z]{2}$/;
if (!CC_RE.test(String(value ?? '').trim().toLowerCase())) {
  throw new Error(`currency must be a 2-letter country code, got: ${value}`);
}

Type guard

function isCountryCode(v) {
  return typeof v === 'string' && /^[a-z]{2}$/.test(v.trim().toLowerCase());
}

Try / catch

try {
  await cmd({ currency: cc });
} catch (e) {
  if (e instanceof ArgumentError && /two-letter storefront country/.test(e.message)) {
    console.error('Use codes like us, cn, jp, de');
  } else throw e;
}

Prevention

When it happens

Trigger: Passing full country names ('usa', 'germany'), three-letter codes ('DEU'), codes with digits or symbols ('u1'), or an empty string that bypassed the default because it was provided explicitly as ''.

Common situations: Users typing 'UK' (fine case-wise, but 'uk' is accepted only if Steam supports it) or 'USA'; config files storing locale strings like 'en-US'; copy-pasting currency codes (USD) instead of country codes.

Related errors


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