nexu-io/open-design · error · Error

no OpenAI credential - configure an API key in Settings or s

Error message

no OpenAI credential - configure an API key in Settings or set OPENAI_API_KEY.

What it means

Thrown at the top of renderOpenAIImage when credentials.apiKey is falsy. The renderer needs a Bearer key to call POST {baseUrl}/v1/images/generations (or the Azure deployment path); without one it refuses before any network call. The constant OPENAI_IMAGE_NO_CREDENTIAL_MESSAGE is reused so the same text reaches image and (via a sibling check) other OpenAI surfaces.

Source

Thrown at apps/daemon/src/media/index.ts:900

  bodyTimeout: OPENAI_IMAGE_BODY_TIMEOUT_MS,
});

function withMediaRequestInit(
  ctx: Pick<MediaContext, 'requestInit'>,
  init: RequestInit = {},
): RequestInit {
  return {
    ...ctx.requestInit,
    ...init,
  };
}

const OPENAI_IMAGE_NO_CREDENTIAL_MESSAGE =
  'no OpenAI credential - configure an API key in Settings or set OPENAI_API_KEY.';

async function renderOpenAIImage(ctx: MediaContext, credentials: ProviderConfig): Promise<RenderResult> {
  if (!credentials.apiKey) {
    throw new Error(OPENAI_IMAGE_NO_CREDENTIAL_MESSAGE);
  }
  const rawBase = credentials.baseUrl || 'https://api.openai.com/v1';
  const azure = detectAzureEndpoint(rawBase);
  const url = buildOpenAIImageUrl(rawBase, azure);

  const body: Record<string, unknown> = {
    prompt: ctx.prompt || 'A high-quality reference image.',
    n: 1,
    size: openaiSizeFor(ctx.model, ctx.aspect),
  };
  // For non-Azure calls, include `model` in the body. Azure infers it
  // from the deployment in the path so omitting it keeps payloads
  // compatible across both flavors. The wire-name (post-alias) goes
  // on the body so the user's alias from issue #1277 reaches the API.
  if (!azure) {
    body.model = ctx.wireModel;
  }
  // Capability branches key off the CATALOG id (not the alias) so a

View on GitHub (pinned to 5be4028344)

Solutions

  1. Set OPENAI_API_KEY in the daemon's environment, or add the key under Settings -> Media Providers -> OpenAI.
  2. If using Azure OpenAI, populate the same apiKey field with the Azure deployment key (baseUrl drives the Azure detection).
  3. Restart the daemon after setting the env var so the new value is read.
  4. Verify with od media providers (or the settings UI) that the OpenAI row shows a configured key.

Example fix

// before
od media generate --surface image --model dall-e-3 --prompt "..."
// after
export OPENAI_API_KEY=sk-...
od media generate --surface image --model dall-e-3 --prompt "..."
Defensive patterns

Strategy: validation

Validate before calling

function ensureOpenAICredential(creds: {apiKey?: string} | null): asserts creds is { apiKey: string } {
  if (!creds?.apiKey) {
    throw new Error('no OpenAI credential - configure an API key in Settings or set OPENAI_API_KEY.');
  }
}
ensureOpenAICredential(credentials);

Type guard

function hasOpenAIKey(c: {apiKey?:string} | null): c is { apiKey: string } {
  return Boolean(c && typeof c.apiKey === 'string' && c.apiKey.length > 0);
}

Prevention

When it happens

Trigger: Selecting an OpenAI image model (dall-e-*, gpt-image-*) with no OpenAI provider credential stored and no OPENAI_API_KEY env var; credentials saved under a different provider key; Settings page saved an empty key.

Common situations: Fresh install; user moved env vars out of the shell rc; key was deleted from the credentials store but the UI still shows the model as selectable; BYOK path where the daemon process does not inherit the user's shell env.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/32614c42de270de1. Report an issue: GitHub.