jackwener/OpenCLI · error · CliError

CONFIG

CONFIG

Error message

Missing Spotify credentials.

1. Go to https://developer.spotify.com/dashboard and create an app
2. Add http://127.0.0.1:8888/callback as a Redirect URI
3. Copy your Client ID and Client Secret
4. Open the file: ${envFile}
5. Fill in SPOTIFY_CLIENT_ID and SPOTIFY_CLIENT_SECRET, then save
6. Run: opencli spotify auth

What it means

assertSpotifyCredentialsConfigured throws this CliError with code 'CONFIG' when the loaded Spotify credentials are absent or still placeholder values. The opencli Spotify integration requires a developer app's client ID/secret to run the OAuth flow, so it fails fast with step-by-step setup instructions instead of making doomed API calls. It only passes when hasConfiguredSpotifyCredentials finds non-placeholder clientId and clientSecret.

Source

Thrown at clis/spotify/utils.js:38

        clientSecret: processEnv.SPOTIFY_CLIENT_SECRET || fileEnv.SPOTIFY_CLIENT_SECRET || '',
    };
}
export function isPlaceholderCredential(value) {
    const normalized = value?.trim() || '';
    if (!normalized)
        return false;
    return SPOTIFY_PLACEHOLDER_PATTERNS.some(pattern => pattern.test(normalized));
}
export function hasConfiguredSpotifyCredentials(credentials) {
    return Boolean(credentials.clientId.trim()) &&
        Boolean(credentials.clientSecret.trim()) &&
        !isPlaceholderCredential(credentials.clientId) &&
        !isPlaceholderCredential(credentials.clientSecret);
}
export function assertSpotifyCredentialsConfigured(credentials, envFile) {
    if (hasConfiguredSpotifyCredentials(credentials))
        return;
    throw new CliError('CONFIG', `Missing Spotify credentials.\n\n` +
        `1. Go to https://developer.spotify.com/dashboard and create an app\n` +
        `2. Add ${'http://127.0.0.1:8888/callback'} as a Redirect URI\n` +
        `3. Copy your Client ID and Client Secret\n` +
        `4. Open the file: ${envFile}\n` +
        `5. Fill in SPOTIFY_CLIENT_ID and SPOTIFY_CLIENT_SECRET, then save\n` +
        `6. Run: opencli spotify auth`);
}
export function mapSpotifyTrackResults(data) {
    const items = data?.tracks?.items;
    if (!Array.isArray(items))
        return [];
    return items.map((track) => ({
        track: track?.name || '',
        artist: Array.isArray(track?.artists) ? track.artists.map((artist) => artist.name).join(', ') : '',
        album: track?.album?.name || '',
        uri: track?.uri || '',
    }));
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Create an app at https://developer.spotify.com/dashboard and add http://127.0.0.1:8888/callback as a Redirect URI
  2. Copy the Client ID and Client Secret into the env file shown in the error message as SPOTIFY_CLIENT_ID and SPOTIFY_CLIENT_SECRET, then save
  3. Run: opencli spotify auth
  4. Re-run your original command; ensure the values are real (no placeholder/sample text) so isPlaceholderCredential passes

Example fix

// before (.env)
SPOTIFY_CLIENT_ID=your_client_id_here
SPOTIFY_CLIENT_SECRET=

// after (.env)
SPOTIFY_CLIENT_ID=4f2a9c8b1d3e4f5a6b7c8d9e0f1a2b3c
SPOTIFY_CLIENT_SECRET=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
Defensive patterns

Strategy: validation

Validate before calling

import { readFileSync, existsSync } from 'node:fs';

function spotifyCredentialsLookConfigured(envPath = '.env') {
  if (!existsSync(envPath)) return { ok: false, reason: `${envPath} does not exist` };
  const env = readFileSync(envPath, 'utf8');
  const get = (k) => {
    const m = env.match(new RegExp(`^${k}=(.*)$`, 'm'));
    return m ? m[1].trim() : '';
  };
  const id = get('SPOTIFY_CLIENT_ID');
  const secret = get('SPOTIFY_CLIENT_SECRET');
  const placeholder = (v) => !v || /your_|placeholder|xxx|<.*>/i.test(v);
  if (placeholder(id)) return { ok: false, reason: 'SPOTIFY_CLIENT_ID missing or placeholder' };
  if (placeholder(secret)) return { ok: false, reason: 'SPOTIFY_CLIENT_SECRET missing or placeholder' };
  return { ok: true };
}
// run before invoking any opencli spotify command

Type guard

function hasConfiguredSpotifyCredentials(c) {
  return typeof c === 'object' && c !== null &&
    typeof c.clientId === 'string' && c.clientId.length > 0 &&
    typeof c.clientSecret === 'string' && c.clientSecret.length > 0 &&
    !isPlaceholderCredential(c.clientId) &&
    !isPlaceholderCredential(c.clientSecret);
}

Try / catch

import { CliError } from '@jackwener/opencli/errors';

try {
  await runSpotifyCommand(args);
} catch (e) {
  if (e instanceof CliError && e.code === 'CONFIG') {
    console.error('Spotify not configured. Follow these steps:\n' + e.message);
    process.exitCode = 1;
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Any opencli Spotify command calls assertSpotifyCredentialsConfigured(credentials, envFile); it throws when SPOTIFY_CLIENT_ID or SPOTIFY_CLIENT_SECRET is missing from the env file, empty, or matches the placeholder values detected by isPlaceholderCredential (e.g. copy-pasted sample values like 'your_client_id_here').

Common situations: Fresh clone of the repo without creating a .env file; created a Spotify app but never copied the credentials into the env file; left the template placeholder strings in place; wrote credentials to the wrong env file path; using a different Spotify account's app than expected.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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