abhigyanpatwari/GitNexus · error

Unsupported local provider: ${provider satisfies never}

Error message

Unsupported local provider: ${provider satisfies never}

What it means

Exhaustiveness guard at the end of localModelConfigKey in wiki.ts. The function maps each supported local provider ('cursor' | 'claude' | 'codex' | 'opencode' | 'grok') to its config key; the `provider satisfies never` throw is unreachable for well-typed callers and fires only when a provider string outside the union reaches it (e.g. via untyped JSON, an env var, or a newly added provider missing a mapping).

Source

Thrown at gitnexus/src/cli/wiki.ts:85

function isLocalProvider(
  provider: LLMProvider | undefined,
): provider is 'cursor' | 'claude' | 'codex' | 'opencode' | 'grok' {
  return (
    provider === 'cursor' ||
    provider === 'claude' ||
    provider === 'codex' ||
    provider === 'opencode' ||
    provider === 'grok'
  );
}

function localModelConfigKey(provider: 'cursor' | 'claude' | 'codex' | 'opencode' | 'grok') {
  if (provider === 'cursor') return 'cursorModel';
  if (provider === 'claude') return 'claudeModel';
  if (provider === 'codex') return 'codexModel';
  if (provider === 'opencode') return 'opencodeModel';
  if (provider === 'grok') return 'grokModel';
  throw new Error(`Unsupported local provider: ${provider satisfies never}`);
}

/**
 * Prompt the user for input via stdin.
 */
function prompt(question: string, hide = false): Promise<string> {
  return new Promise((resolve) => {
    const rl = readline.createInterface({
      input: process.stdin,
      output: process.stdout,
    });

    if (hide && process.stdin.isTTY) {
      // Mask input for API keys
      process.stdout.write(question);
      let input = '';
      process.stdin.setRawMode(true);
      process.stdin.resume();

View on GitHub (pinned to 52924ef12c)

Solutions

  1. Correct the provider value to one of: cursor, claude, codex, opencode, grok (exact, lowercase spelling).
  2. If the value comes from config/JSON, validate it against the allowed provider union before calling.
  3. If you added a new provider type, extend localModelConfigKey with a mapping branch for it before the throw.
  4. Let TypeScript check exhaustiveness: keep the parameter typed as the literal union so `satisfies never` fails at compile time, not runtime.

Example fix

// before
function localModelConfigKey(provider: 'cursor' | 'claude' | 'codex' | 'opencode' | 'grok') {
  if (provider === 'cursor') return 'cursorModel';
  // ... grok mapped, new provider 'windsurf' missing

// after
function localModelConfigKey(provider: 'cursor' | 'claude' | 'codex' | 'opencode' | 'grok' | 'windsurf') {
  if (provider === 'cursor') return 'cursorModel';
  // ...
  if (provider === 'windsurf') return 'windsurfModel';
  throw new Error(`Unsupported local provider: ${provider satisfies never}`);
Defensive patterns

Strategy: type-guard

Validate before calling

const LOCAL_PROVIDERS = ['cursor', 'claude', 'codex', 'opencode', 'grok'] as const;
type LocalProvider = typeof LOCAL_PROVIDERS[number];
function parseProvider(v: string): LocalProvider {
  if (!(LOCAL_PROVIDERS as readonly string[]).includes(v)) {
    throw new Error(`Unsupported local provider: ${v}`);
  }
  return v as LocalProvider;
}

Type guard

function isLocalProvider(v: unknown): v is 'cursor' | 'claude' | 'codex' | 'opencode' | 'grok' {
  return v === 'cursor' || v === 'claude' || v === 'codex' || v === 'opencode' || v === 'grok';
}

Try / catch

try {
  const key = localModelConfigKey(provider);
} catch (e) {
  if (e.message.startsWith('Unsupported local provider:')) {
    console.error(`${e.message} — expected one of cursor, claude, codex, opencode, grok`);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling localModelConfigKey with a cast/loosely-typed value like `provider as any`, config/CLI input carrying a provider name not in the union (e.g. 'gemini-local'), or a new provider added to a wider type without extending this function's if-chain.

Common situations: Typo in a config file provider field ('claude ' with trailing space, wrong casing), third-party tooling injecting provider strings, or a contributor adding a provider to the wiki command without updating localModelConfigKey.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@52924ef12c (2026-09-01). Data as JSON: /api/errors/d7d459d7c5d19dbd. Report an issue: GitHub.