jackwener/OpenCLI · error · EmptyResultError

Steam app id ${appId} returned no data (may be region-locked

Error message

Steam app id ${appId} returned no data (may be region-locked or removed).

What it means

The Steam appdetails endpoint responded, but the wrapper for the app id either is missing, has success:false, or has no data field. The CLI converts this into EmptyResultError, noting that region-locking or removal are common causes.

Source

Thrown at clis/steam/app.js:43

    strategy: Strategy.PUBLIC,
    browser: false,
    args: [
        { name: 'id', positional: true, required: true, help: 'Numeric Steam app id (e.g. "620" for Portal 2)' },
        { name: 'currency', default: 'us', help: 'Storefront country code (e.g. us / cn / jp / de)' },
    ],
    columns: [
        'id', 'name', 'type', 'isFree', 'releaseDate', 'developers', 'publishers',
        'price', 'currency', 'metacritic', 'recommendations', 'genres', 'categories',
        'shortDescription', 'website', 'url',
    ],
    func: async (args) => {
        const appId = requireAppId(args.id);
        const cc = requireCountryCode(args.currency);
        const url = `${STEAM_STORE}/api/appdetails?appids=${appId}&l=en&cc=${encodeURIComponent(cc)}`;
        const body = await steamFetch(url, `steam app ${appId}`);
        const wrapper = body?.[appId];
        if (!wrapper || wrapper.success !== true || !wrapper.data) {
            throw new EmptyResultError('steam app', `Steam app id ${appId} returned no data (may be region-locked or removed).`);
        }
        const data = wrapper.data;
        const isFree = data.is_free === true;
        const priceFinal = priceCents(data?.price_overview?.final ?? null);
        return [{
            id: String(data.steam_appid ?? appId),
            name: decodeHtmlEntities(data.name ?? ''),
            type: String(data.type ?? ''),
            isFree,
            releaseDate: String(data?.release_date?.date ?? ''),
            developers: Array.isArray(data.developers) ? data.developers.join(', ') : '',
            publishers: Array.isArray(data.publishers) ? data.publishers.join(', ') : '',
            price: isFree ? 0 : priceFinal,
            currency: String(data?.price_overview?.currency ?? '').toUpperCase(),
            metacritic: data?.metacritic?.score != null ? Number(data.metacritic.score) : null,
            recommendations: data?.recommendations?.total != null ? Number(data.recommendations.total) : null,
            genres: joinNames(data.genres),
            categories: joinNames(data.categories),

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the app id via `steam search` or the store URL store.steampowered.com/app/<id>/
  2. Retry with a different currency/country code (e.g. us) in case of region-locking
  3. Check the app page in a browser to confirm it still exists and is purchasable
  4. Handle the EmptyResultError and fall back to cached/other data sources

Example fix

// before
const body = await steamFetch(url, `steam app ${appId}`);
const wrapper = body?.[appId];
if (!wrapper || wrapper.success !== true || !wrapper.data) {
  throw new EmptyResultError(...);
}
// after
const wrapper = body?.[appId];
if (!wrapper?.data) {
  // try fallback region before failing
  const fallback = await steamFetch(url.replace(/cc=[a-z]{2}/, 'cc=us'), `steam app ${appId}`);
  ...
}
Defensive patterns

Strategy: validation

Validate before calling

if (!/^\d+$/.test(appId)) throw new Error(`invalid app id: ${appId}`);
// optionally probe availability first:
const probe = await steamFetch(`${STEAM_STORE}/api/appdetails?appids=${appId}&l=en&cc=us`, 'probe');
if (!probe?.[appId]?.data) throw new Error(`app ${appId} unavailable in us too`);

Type guard

function hasAppData(body, appId) {
  const w = body?.[appId];
  return typeof w === 'object' && w !== null && w.success === true && w.data != null;
}

Try / catch

try {
  const app = await steamApp({ id: appId, currency: cc });
} catch (e) {
  if (e instanceof EmptyResultError) {
    // retry with cc=us or report app unavailable/region-locked
  } else throw e;
}

Prevention

When it happens

Trigger: Nonexistent app id; app not available in the requested country (cc); app removed/delisted from the store; Steam returning success:false for age-gated content without proper cookies.

Common situations: Using an id copied from a community page for a region-restricted game; querying cc=de for apps delisted in Germany; typos in the app id; very old apps that were pulled from the store.

Related errors


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