KeygraphHQ/shannon · error · Error

SHANNON_AI_OPENAI_FORMAT must be one of: ${Object.keys(OPENA

Error message

SHANNON_AI_OPENAI_FORMAT must be one of: ${Object.keys(OPENAI_FORMATS).join(', ')}. Got "${raw}".

What it means

Rejects an invalid value for the SHANNON_AI_OPENAI_FORMAT environment variable. The variable selects which OpenAI wire format a gateway serves and accepts only the keys of OPENAI_FORMATS: 'chat-completions' or 'responses'. Any other value is thrown rather than silently ignored, so the wrong format never reaches a request.

Source

Thrown at apps/worker/src/ai/models.ts:93

/** Format assumed when a gateway is configured but no format is named. */
export const DEFAULT_OPENAI_FORMAT: OpenAiFormat = 'chat-completions';

function isOpenAiFormat(value: string): value is OpenAiFormat {
  return value in OPENAI_FORMATS;
}

/**
 * Read SHANNON_AI_OPENAI_FORMAT. Unset returns undefined, which lets the caller
 * distinguish "not configured" from an explicit choice and reject the variable
 * where it has no effect.
 */
export function resolveOpenAiFormat(): OpenAiFormat | undefined {
  const raw = process.env.SHANNON_AI_OPENAI_FORMAT?.trim();
  if (!raw) return undefined;

  if (!isOpenAiFormat(raw)) {
    throw new Error(
      `SHANNON_AI_OPENAI_FORMAT must be one of: ${Object.keys(OPENAI_FORMATS).join(', ')}. Got "${raw}".`,
    );
  }
  return raw;
}

export interface ModelSpec {
  providerId: string;
  modelId: string;
}

/**
 * Parse a `<provider>:<model-id>` spec. Splits on the first colon only, so colons
 * inside a model ID survive. The provider id is passed through as given — pi's
 * registry validates it later — so this throws only on a malformed spec.
 */
export function parseModelSpec(spec: string): ModelSpec {
  const trimmed = spec.trim();

View on GitHub (pinned to 1ae0a142f8)

Solutions

  1. Set SHANNON_AI_OPENAI_FORMAT to exactly 'chat-completions' or 'responses'.
  2. If you do not need to override the default, unset the variable to fall back to 'chat-completions'.
  3. Double-check shell quoting/export so no trailing whitespace or quotes are attached.

Example fix

// before
export SHANNON_AI_OPENAI_FORMAT=openai-completions   # wrong: that is the pi API id, not the key

// after
export SHANNON_AI_OPENAI_FORMAT=chat-completions
Defensive patterns

Strategy: validation

Validate before calling

const VALID_FORMATS = ['chat-completions', 'responses'] as const;
const raw = process.env.SHANNON_AI_OPENAI_FORMAT?.trim();
if (raw && !(VALID_FORMATS as readonly string[]).includes(raw)) {
  console.error(`Invalid SHANNON_AI_OPENAI_FORMAT="${raw}". Must be one of: ${VALID_FORMATS.join(', ')}`);
  process.exit(1);
}

Type guard

function isOpenAiFormat(value: string): value is 'chat-completions' | 'responses' {
  return value === 'chat-completions' || value === 'responses';
}

Prevention

When it happens

Trigger: Set SHANNON_AI_OPENAI_FORMAT to a value that is not 'chat-completions' or 'responses', then invoke resolveOpenAiFormat() directly or via resolveGatewayFormat()/resolveModelSelection() (e.g. the preflight probe of `./shannon start`).

Common situations: Using the mapped pi API id instead of the key ('openai-completions'), underscores ('chat_completions'), camelCase ('chatCompletions'), or a stale value left over from an older Shannon version after the format names changed.

Related errors


AI-assisted analysis of KeygraphHQ/shannon@1ae0a142f8 (2026-08-12). Data as JSON: /api/errors/8f4a8857b051f812. Report an issue: GitHub.