janhq/jan · error · Error

model.yml not found for ${modelId}

Error message

model.yml not found for ${modelId}

What it means

Thrown by updateMtpSettings() when <provider>/models/<modelId>/model.yml does not exist. The method patches MTP/speculative-decoding fields onto the existing config and re-writes it; without model.yml there is nothing to read or patch. The same guard exists in updateModelSettings() (line 3958) and is the canonical precondition for any per-model config write.

Source

Thrown at extensions/llamacpp-extension/src/index.ts:3904

  }

  async updateMtpSettings(
    modelId: string,
    patch: {
      mtp?: boolean
      spec_draft_n_max?: number | null
      spec_draft_n_min?: number | null
      spec_draft_p_min?: number | null
    }
  ): Promise<void> {
    const configPath = await joinPath([
      await this.getProviderPath(),
      'models',
      modelId,
      'model.yml',
    ])
    if (!(await fs.existsSync(configPath))) {
      throw new Error(`model.yml not found for ${modelId}`)
    }
    const cfg = (await invoke<ModelConfig>('read_yaml', { path: configPath })) as ModelConfig & {
      mtp?: boolean
      spec_draft_n_max?: number
      spec_draft_n_min?: number
      spec_draft_p_min?: number
    }

    if (typeof patch.mtp === 'boolean') cfg.mtp = patch.mtp
    const assignNumeric = (
      key: 'spec_draft_n_max' | 'spec_draft_n_min' | 'spec_draft_p_min',
      value: number | null | undefined
    ) => {
      if (value === null) {
        delete cfg[key]
      } else if (typeof value === 'number' && Number.isFinite(value)) {
        cfg[key] = value
      }

View on GitHub (pinned to fad3f12a14)

Solutions

  1. Ensure the model is fully imported (import() resolved, model.yml on disk) before updating MTP settings.
  2. Pre-check fs.existsSync(configPath) and disable the MTP controls in the UI until it exists.
  3. If model.yml was lost, re-import the model.
  4. Verify the modelId casing/spelling matches the imported id.

Example fix

// before
await provider.updateMtpSettings('qwen', { mtp: true }) // throws - not imported yet
// after - gate on import completion
const yml = await joinPath([await provider.getProviderPath(), 'models', 'qwen', 'model.yml'])
if (!(await fs.existsSync(yml))) { throw new Error('model not fully imported yet') }
await provider.updateMtpSettings('qwen', { mtp: true })
Defensive patterns

Strategy: validation

Validate before calling

// Ensure model.yml exists before patching MTP settings
const yml = await joinPath([await provider.getProviderPath(), 'models', modelId, 'model.yml'])
if (!(await fs.existsSync(yml))) {
  throw new Error(`Cannot update MTP settings: '${modelId}' is not fully imported (model.yml missing)`)
}

Type guard

async function modelConfigExists(provider: { getProviderPath(): Promise<string> }, id: string): Promise<boolean> {
  const yml = await joinPath([await provider.getProviderPath(), 'models', id, 'model.yml'])
  return fs.existsSync(yml)
}

Try / catch

try { await provider.updateMtpSettings(modelId, patch) }
catch (e) {
  if (/model\.yml not found/.test(String(e))) { /* disable MTP UI until import finishes */ }
  else throw e
}

Prevention

When it happens

Trigger: Calling updateMtpSettings on an id that was never imported or was deleted; the model folder exists but model.yml is missing (corrupt/partial import); wrong id (typo/case); calling it before import() has finished writing model.yml.

Common situations: UI lets the user open MTP settings for a model still downloading (model.yml not yet written). Migrating models by copying weight files but forgetting model.yml. Race: import failed validation but the UI still shows the row. Case-insensitive FS id mismatch.

Related errors


AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12). Data as JSON: /api/errors/42a74608cd081351. Report an issue: GitHub.