{"record":{"id":"c4bac1c4b6027069","repo":"invoke-ai/InvokeAI","slug":"the-model-with-key-key-is-not-a-main-sd-1-2-xl-c","errorCode":null,"errorMessage":"The model with key {key} is not a main SD 1/2/XL checkpoint model.","messagePattern":"The model with key (.+?) is not a main SD 1/2/XL checkpoint model\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"invokeai/app/api/routers/model_manager.py","lineNumber":1296,"sourceCode":"\n    try:\n        model_config = store.get_model(key)\n    except UnknownModelException as e:\n        logger.error(str(e))\n        raise HTTPException(status_code=424, detail=str(e))\n\n    if not isinstance(\n        model_config,\n        (\n            Main_Checkpoint_SD1_Config,\n            Main_Checkpoint_SD2_Config,\n            Main_Checkpoint_SDXL_Config,\n            Main_Checkpoint_SDXLRefiner_Config,\n        ),\n    ):\n        msg = f\"The model with key {key} is not a main SD 1/2/XL checkpoint model.\"\n        logger.error(msg)\n        raise HTTPException(400, msg)\n\n    # Under the models root so `install_path` below moves the result rather than copying it across\n    # a filesystem boundary, but inside the scratch directory the orphan scan skips: a half-written\n    # diffusers copy is model files with no database record, which is exactly what that scan hunts\n    # for, and `DELETE /sync/orphaned` would rmtree it while it is still being written.\n    scratch_dir = ApiDependencies.invoker.services.configuration.models_path / CONVERSION_SCRATCH_DIRNAME\n    scratch_dir.mkdir(parents=True, exist_ok=True)\n\n    with TemporaryDirectory(dir=scratch_dir) as tmpdir:\n        convert_path = pathlib.Path(tmpdir) / pathlib.Path(model_config.path).stem\n        converted_model = loader.load_model(model_config, user_id=user_id)\n        # write the converted file to the convert path\n        raw_model = converted_model.model\n        assert hasattr(raw_model, \"save_pretrained\")\n        raw_model.save_pretrained(convert_path)  # type: ignore\n        assert convert_path.exists()\n\n        # temporarily rename the original safetensors file so that there is no naming conflict","sourceCodeStart":1278,"sourceCodeEnd":1314,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/api/routers/model_manager.py#L1278-L1314","documentation":"HTTP 400 raised by POST /models/convert/{key} when the model record for the given key is not one of the main SD1/SD2/SDXL/SDXL-Refiner checkpoint configs. The converter only knows how to transform a single-file checkpoint model into a diffusers folder; other model types (LoRAs, VAEs, ControlNets, diffusers-format mains) have nothing to convert. The isinstance check against the four config classes is the guard.","triggerScenarios":"Calling convert_model (POST /api/v1/models/convert/{key}) with the key of a model whose stored config class is not Main_Checkpoint_SD1_Config / SD2 / SDXL / SDXLRefiner — e.g. converting a diffusers-format main model, a LoRA, VAE, ControlNet, or T2I adapter.","commonSituations":"Users selecting the wrong model in the UI conversion dialog; scripts iterating all model keys and converting each; trying to 'convert' an already-converted diffusers model; confusing a LoRA key with a main model key.","solutions":["Verify the model key refers to a main checkpoint model (SD1/SD2/SDXL/Refiner) in the model manager","Call GET /api/v1/models/i/{key} and confirm its type/base are main checkpoint, not LoRA/VAE/ControlNet/diffusers-main","If the model is already diffusers format, no conversion is needed — use it directly","If you intended to convert a different model, fetch the correct key from the model list"],"exampleFix":"// before: blind conversion of any key\nawait api.convertModel(key);\n// after: check type first\nconst cfg = await api.getModelConfig(key);\nif (cfg.type === 'main' && cfg.format === 'checkpoint') await api.convertModel(key);\nelse throw new Error(`Model ${key} is not convertible`);","handlingStrategy":"validation","validationCode":"const cfg = await api.getModelConfig(key);\nif (!(cfg.type === 'main' && cfg.format === 'checkpoint')) {\n  throw new Error(`Model ${key} (${cfg.type}/${cfg.format}) cannot be converted`);\n}","typeGuard":"function isConvertibleMainCheckpoint(cfg) {\n  return cfg != null && cfg.type === 'main' && cfg.format === 'checkpoint';\n}","tryCatchPattern":"try {\n  await api.convertModel(key);\n} catch (e) {\n  if (e.status === 400 && /not a main SD/.test(e.body?.detail ?? '')) {\n    console.warn(`Skip ${key}: not a checkpoint model`);\n  } else throw e;\n}","preventionTips":["Check the model's type/format via the model config endpoint before converting","Never iterate all model keys blindly converting each one","Remember diffusers-format main models do not need conversion","Label checkpoint vs diffusers models in any custom UI"],"tags":["http-400","model-manager","checkpoint-conversion"],"backgroundTag":"unsupported-model-type-for-conversion","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}