nexu-io/open-design · error · Error

unsupported leonardo.ai model: ${ctx.model}

Error message

unsupported leonardo.ai model: ${ctx.model}

What it means

Thrown by renderLeonardoImage when ctx.model is not a key in the static modelMap. The map holds four Leonardo platform model IDs (phoenix, kino-xl, flux-dev, flux-schnell, anime-pastel); any other model identifier reaches the `if (!platformModelId)` branch. This guards against pushing an unknown model ID to Leonardo's API which would 400 upstream.

Source

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

  if (!credentials.apiKey) {
    throw new Error(
      'no Leonardo.ai API key — configure it in Settings or set LEONARDO_API_KEY',
    );
  }
  const baseUrl = (credentials.baseUrl || 'https://cloud.leonardo.ai/api/rest/v1').replace(/\/$/, '');
  
  // Map model IDs to Leonardo.ai platform model IDs
  const modelMap: Record<string, string> = {
    'leonardo-phoenix': '6b645e3a-d64f-4341-a6d8-7a3690fbf042',  // Phoenix
    'leonardo-kino-xl': 'aa77f04e-3eec-4034-9c07-d0f619684628',  // Kino XL
    'leonardo-flux-dev': 'b2614463-296c-462a-9586-aafdb8f00e36', // FLUX.1 [dev]
    'leonardo-flux-schnell': '1dd50843-d653-4516-a8e3-f0238ee453ff', // FLUX.1 [schnell]
    'leonardo-anime-pastel': '1e60896f-3c26-4296-8ecc-53e2afecc132', // Anime Pastel Dream
  };
  
  const platformModelId = modelMap[ctx.model];
  if (!platformModelId) {
    throw new Error(`unsupported leonardo.ai model: ${ctx.model}`);
  }
  
  // Map aspect ratios to Leonardo.ai dimensions
  const aspectMap: Record<string, { width: number; height: number }> = {
    '1:1': { width: 1024, height: 1024 },
    '16:9': { width: 1344, height: 768 },
    '9:16': { width: 768, height: 1344 },
    '4:3': { width: 1152, height: 896 },
    '3:4': { width: 896, height: 1152 },
  };
  
  const size = (ctx.aspect ? aspectMap[ctx.aspect] : undefined) || { width: 1024, height: 1024 };
  
  // Submit generation request. Phoenix and the FLUX family require the
  // `contrast` field per Leonardo's API reference; valid values are
  // 3 (Low) / 3.5 (Medium) / 4 (High). Default to 3.5 so prompts that
  // omit a contrast hint fall in the middle of the supported range.
  const requiresContrast =

View on GitHub (pinned to 5be4028344)

Solutions

  1. Use one of the supported model IDs: leonardo-phoenix, leonardo-kino-xl, leonardo-flux-dev, leonardo-flux-schnell, or leonardo-anime-pastel.
  2. If you need a newly released Leonardo model, extend the modelMap in apps/daemon/src/media/index.ts (around line 2185) and rebuild the daemon.
  3. Check for typos: the prefix is 'leonardo-' (lowercase, hyphen-separated), not 'leonardo_' or 'Leonardo-'.
  4. If invoking through a skill/template, inspect the rendered prompt to confirm which model string it actually sent.

Example fix

// before
ctx.model = 'leonardo-flux' // not in the map → [463]

// after
ctx.model = 'leonardo-flux-dev' // valid map key
Defensive patterns

Strategy: validation

Validate before calling

// Validate the model id is supported before reaching the renderer.
const LEONARDO_SUPPORTED_MODELS = new Set([
  'leonardo-phoenix',
  'leonardo-kino-xl',
  'leonardo-flux-dev',
  'leonardo-flux-schnell',
  'leonardo-anime-pastel',
]);
function assertLeonardoModelSupported(model: string): void {
  if (!LEONARDO_SUPPORTED_MODELS.has(model)) {
    throw new Error(
      `unsupported leonardo.ai model: ${model}. Supported: ${[...LEONARDO_SUPPORTED_MODELS].join(', ')}`,
    );
  }
}

Type guard

function isLeonardoSupportedModel(m: string): m is
  | 'leonardo-phoenix'
  | 'leonardo-kino-xl'
  | 'leonardo-flux-dev'
  | 'leonardo-flux-schnell'
  | 'leonardo-anime-pastel' {
  return LEONARDO_SUPPORTED_MODELS.has(m);
}

Prevention

When it happens

Trigger: User (or a skill/template) passes a model string not in {'leonardo-phoenix','leonardo-kino-xl','leonardo-flux-dev','leonardo-flux-schnell','leonardo-anime-pastel'} to the Leonardo renderer — e.g. a typo, a deprecated ID, or a model the dispatcher routed incorrectly.

Common situations: Typo in a skill prompt or template that names the model; Leonardo renamed/added a model and the user expects the new ID before the map is updated; a legacy project file references an old model alias.

Related errors


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