{"record":{"id":"4553066d11093870","repo":"cjpais/Handy","slug":"device-index-index-cannot-host-a-model","errorCode":null,"errorMessage":"Device index {index} ({}) cannot host a model","messagePattern":"Device index (.+?) \\((.+?)\\) cannot host a model","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/src/managers/transcription.rs","lineNumber":1940,"sourceCode":"        .collect()\n}\n\n/// Resolve a `--list-devices` registry index to an exact opaque device handle\n/// for a transcribe-cpp model load (the `--device-index` flag). In 0.2 index 0\n/// is an exact selection too; only an omitted index requests automatic device\n/// selection. Errors if the index isn't a registered, loadable primary device.\nfn resolve_device_index(index: usize) -> Result<(Backend, Option<transcribe_cpp::Device>)> {\n    let device = transcribe_compute_devices()\n        .into_iter()\n        .find(|d| d.index == Some(index))\n        .ok_or_else(|| {\n            anyhow::anyhow!(\"No compute device with index {index} (see --list-devices)\")\n        })?;\n    if matches!(\n        device.device_type,\n        transcribe_cpp::DeviceType::Accel | transcribe_cpp::DeviceType::Unknown\n    ) {\n        return Err(anyhow::anyhow!(\n            \"Device index {index} ({}) cannot host a model\",\n            device.kind\n        ));\n    }\n\n    // 0.2's opaque handle makes every index, including zero, an exact\n    // selection. Backend::Auto accepts any primary device and cannot conflict\n    // with the selected device's vendor backend.\n    Ok((Backend::Auto, Some(device)))\n}\n\n/// Map Handy's whisper accelerator setting to a transcribe-cpp [`Backend`].\n///\n/// `Auto` lets the library pick the best device (with CPU fallback), while\n/// `Cpu` forces strict CPU. `Gpu` only remains as the companion setting for an\n/// exact device; without a valid exact device it has the retired generic GPU\n/// state's new Auto semantics. An emulated x64 process on Windows ARM64 forces\n/// strict CPU for every setting.","sourceCodeStart":1922,"sourceCodeEnd":1958,"githubUrl":"https://github.com/cjpais/Handy/blob/fbd4e15fa14a721c66c57006ae110428b9e255b3/src-tauri/src/managers/transcription.rs#L1922-L1958","documentation":"Handy throws this from resolve_device_index (src-tauri/src/managers/transcription.rs:1940) when an explicit device selection (--device-index N, or load_model_with_device(model_id, Some(n))) resolves to a registered transcribe-cpp device whose DeviceType is Accel or Unknown. The index itself is valid — it matched an entry in transcribe_compute_devices() (otherwise the 'No compute device with index' error at line 1934 fires) — but the matched entry is a helper accelerator or an unclassifiable device, and only primary compute devices (CPU, Gpu, Igpu) can host a Whisper-family GGML model. The model load is aborted: a 'loading_failed' model-state event is emitted and the headless --transcribe-file run exits with the error.","triggerScenarios":"Running `handy --transcribe-file audio.wav --device-index N` where N is the --list-devices index of an entry with kind=accel or an unknown-type entry; or calling TranscriptionManager::load_model_with_device(model_id, Some(n)) in Rust with such an index. Concretely: the device registry lists something like `index=1 kind=accel name=... vram=0MB` and you pass --device-index 1. Also triggered when the registry shrank or shifted between runs — e.g. on a Windows x64 build running emulated on an ARM64 host, GPU entries are filtered out of transcribe_compute_devices() (transcription.rs:2076-2087) leaving only cpu/accel kinds, so an index that used to hit a GPU now hits an accel entry; or a backend init failure (logged as 'Failed to initialize transcribe-cpp backends') changed which devices registered.","commonSituations":"Hard-coding a device index in a script/WM config that was observed on a different machine or an earlier run — indices are process-local and shift when drivers, eGPU hot-plug, or backend availability change. Machines that register accelerator entries (kind=accel) alongside GPU/CPU, where the user picks the wrong line from --list-devices output. Windows-on-ARM emulation setups where the GPU entries are hidden and users assume index 1 is still the discrete GPU. Storing a raw registry index in automation instead of a stable device identity (the settings layer deliberately stores a device key, not an index).","solutions":["Run `handy --list-devices` and re-check the index you passed: pick an entry whose kind is cpu, gpu, or igpu (vram>0MB usually indicates a real GPU), never kind=accel or an entry with no recognizable kind.","Omit --device-index entirely and let the persisted accelerator setting pick (Backend::Auto handles CPU fallback); you only need an explicit index for exact multi-GPU selection.","If you expected a GPU at that index, check the startup log line 'transcribe-cpp initialized with N compute device(s): [...]' — a 'Failed to initialize transcribe-cpp backends' warning means fewer devices registered, shifting indices; fix the backend init (drivers, Vulkan/Metal availability) and re-list devices.","On Windows x64 running emulated on an ARM64 host, GPU devices are intentionally filtered out (only cpu/accel remain), so no index will select a GPU — run a native ARM64 build or omit --device-index to use CPU.","For API callers of load_model_with_device: validate the index against transcribe_cpp::devices() and reject DeviceType::Accel/Unknown before invoking the load (see validation code below)."],"exampleFix":"# before — index 1 is an accel entry, load aborts\n$ handy --list-devices\nindex=0 kind=cpu name=AMD Ryzen ... vram=0MB\nindex=1 kind=accel name=... vram=0MB\nindex=2 kind=gpu name=NVIDIA GeForce RTX ... vram=8192MB\n$ handy --transcribe-file audio.wav --device-index 1\nError: Device index 1 (accel) cannot host a model\n\n# after — select a primary device (gpu/cpu), or drop the flag for automatic selection\n$ handy --transcribe-file audio.wav --device-index 2\n$ handy --transcribe-file audio.wav   # uses persisted accelerator setting (Auto)","handlingStrategy":"validation","validationCode":"// Run before load_model_with_device(model_id, Some(index)) — mirrors\n// resolve_device_index's rule: index must exist AND be a primary device.\nuse transcribe_cpp::DeviceType;\n\nfn device_index_can_host_model(index: usize) -> bool {\n    transcribe_cpp::devices()\n        .into_iter()\n        .any(|d| d.index == Some(index)\n            && !matches!(d.device_type, DeviceType::Accel | DeviceType::Unknown))\n}\n\n// before loading:\nif !device_index_can_host_model(idx) {\n    // re-enumerate, log describe_compute_devices(), and fall back to None\n    // (automatic selection) or fail fast with a clear message\n}\ntm.load_model_with_device(&model_id, Some(idx))?;","typeGuard":"// Rust predicate narrowing a Device to 'can host a model' (primary compute).\nfn is_primary_compute_device(d: &transcribe_cpp::Device) -> bool {\n    !matches!(\n        d.device_type,\n        transcribe_cpp::DeviceType::Accel | transcribe_cpp::DeviceType::Unknown\n    )\n}","tryCatchPattern":"// If you still call with an explicit index, catch and retry once with\n// automatic selection so a shifted registry doesn't kill the job:\nmatch tm.load_model_with_device(&model_id, Some(idx)) {\n    Ok(()) => {}\n    Err(e) if e.to_string().contains(\"cannot host a model\") => {\n        log::warn!(\"device index {idx} unusable, retrying with automatic selection: {e}\");\n        tm.load_model_with_device(&model_id, None)?;\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always run --list-devices in the same environment and run before passing --device-index; registry indices are process-local and shift when drivers or backend availability change.","Prefer omitting --device-index (automatic selection with CPU fallback) unless you specifically need an exact device on a multi-GPU machine.","Never persist a raw --list-devices index across sessions; store a stable device identity like the settings layer does (transcribe_device_key uses device_id or name, not index).","Check the startup log 'transcribe-cpp initialized with N compute device(s)' to confirm which devices actually registered before trusting an index.","On Windows x64 emulated under ARM64, expect only cpu/accel entries — no index selects a GPU there; use a native build or CPU."],"tags":["rust","tauri","transcribe-cpp","gpu","device-selection","cli","whisper","headless-transcription"],"backgroundTag":"unsupported-device-type","analyzedSha":"fbd4e15fa14a721c66c57006ae110428b9e255b3","analyzedAt":"2026-08-22T10:26:11.153Z","contentChangedAt":"2026-08-22T10:26:11.153Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}