nexu-io/open-design · error · Error

no ImageRouter API key — configure it in Settings or set OD_

Error message

no ImageRouter API key — configure it in Settings or set OD_IMAGEROUTER_API_KEY

What it means

Thrown at the top of renderImageRouterImage when credentials.apiKey is falsy. ImageRouter is an OpenAI-compatible gateway reached at IMAGEROUTER_DEFAULT_BASE_URL (https://api.imagerouter.io/v1/openai); the renderer refuses to call /images/generations without a Bearer key. The env var OD_IMAGEROUTER_API_KEY is the documented override.

Source

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

    const imgResp = await fetch(entry.url, withMediaRequestInit(ctx));
    if (!imgResp.ok) throw new Error(`openai image fetch ${imgResp.status}`);
    const arr = await imgResp.arrayBuffer();
    bytes = Buffer.from(arr);
  } else {
    throw new Error('openai response had neither b64_json nor url');
  }

  const tag = azure ? 'azure-openai' : 'openai';
  return {
    bytes,
    providerNote: `${tag}/${ctx.wireModel} · ${ctx.aspect} · ${bytes.length} bytes`,
    suggestedExt: '.png',
  };
}

async function renderImageRouterImage(ctx: MediaContext, credentials: ProviderConfig): Promise<RenderResult> {
  if (!credentials.apiKey) {
    throw new Error(
      'no ImageRouter API key — configure it in Settings or set OD_IMAGEROUTER_API_KEY',
    );
  }
  const baseUrl = (credentials.baseUrl || IMAGEROUTER_DEFAULT_BASE_URL).trim();
  const wireModel = (credentials.model || ctx.wireModel).trim();
  const url = buildOpenAIImageUrl(baseUrl, false);
  const body: Record<string, unknown> = {
    prompt: ctx.prompt || 'A high-quality reference image.',
    model: wireModel,
    quality: 'auto',
    size: imageRouterSizeFor(ctx.aspect, 'image'),
    response_format: 'b64_json',
    output_format: 'png',
  };

  const resp = await fetch(url, withMediaRequestInit(ctx, {
    method: 'POST',
    headers: {

View on GitHub (pinned to 5be4028344)

Solutions

  1. Set OD_IMAGEROUTER_API_KEY in the daemon environment or add the key under Settings -> Media Providers -> ImageRouter.
  2. Restart the daemon so the new env value is read.
  3. Confirm with od media providers that ImageRouter shows a configured key.
  4. Switch to the direct OpenAI provider if you have an OpenAI key instead.

Example fix

// before
od media generate --surface image --model <imagerouter-model> --prompt "..."
// after
export OD_IMAGEROUTER_API_KEY=sk-ir-...
od media generate --surface image --model <imagerouter-model> --prompt "..."
Defensive patterns

Strategy: validation

Validate before calling

function ensureImageRouterCredential(creds: {apiKey?: string} | null): asserts creds is { apiKey: string } {
  if (!creds?.apiKey) {
    throw new Error('no ImageRouter API key — configure it in Settings or set OD_IMAGEROUTER_API_KEY');
  }
}
ensureImageRouterCredential(credentials);

Type guard

function hasImageRouterKey(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 ImageRouter-routed image model with no ImageRouter credential stored and no OD_IMAGEROUTER_API_KEY env var; key cleared from Settings but model still selected.

Common situations: User added an OpenAI key but ImageRouter needs its own; env var not exported in the daemon's process; trial key expired.

Related errors


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