{"record":{"id":"b75e83d29d217cc0","repo":"spacedriveapp/spacedrive","slug":"no-paired-devices-found-pair-a-device-first-with","errorCode":null,"errorMessage":"No paired devices found.\nPair a device first with:\nsd network pair generate  # on this device\nsd network pair join <code>  # on the other device","messagePattern":"No paired devices found\\.\nPair a device first with:\nsd network pair generate  # on this device\nsd network pair join <code>  # on the other device","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"apps/cli/src/domains/library/mod.rs","lineNumber":307,"sourceCode":"\n\tlet library_idx = select(\"Select local library to sync\", &library_choices)?;\n\tlet local_library_id = libraries[library_idx].id;\n\n\tprintln!(\n\t\t\"\\n✓ Selected local library: {}\\n\",\n\t\tlibraries[library_idx].name\n\t);\n\n\t// Step 2: Select remote device from paired devices\n\tlet paired_devices: ListPairedDevicesOutput = execute_core_query!(\n\t\tctx,\n\t\tListPairedDevicesInput {\n\t\t\tconnected_only: false\n\t\t}\n\t);\n\n\tif paired_devices.devices.is_empty() {\n\t\tanyhow::bail!(\n\t\t\t\"No paired devices found.\\n\\\n\t\t\tPair a device first with:\\n\\\n\t\t\t  sd network pair generate  # on this device\\n\\\n\t\t\t  sd network pair join <code>  # on the other device\"\n\t\t);\n\t}\n\n\tlet device_choices: Vec<String> = paired_devices\n\t\t.devices\n\t\t.iter()\n\t\t.map(|d| {\n\t\t\tlet status = if d.is_connected {\n\t\t\t\t\"connected\"\n\t\t\t} else {\n\t\t\t\t\"paired\"\n\t\t\t};\n\t\t\tformat!(\"{} - {} ({})\", d.name, d.os_version, status)\n\t\t})","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/spacedriveapp/spacedrive/blob/6dfeccf2113039e35f2ce735f945e70dc3e4ea45/apps/cli/src/domains/library/mod.rs#L289-L325","documentation":"Thrown by the interactive 'sd library sync' wizard (step 2) after it queries the daemon with ListPairedDevicesInput { connected_only: false } and receives an empty devices list. It aborts the wizard before any device selection because library sync requires a peer device. The message itself tells you the pairing commands to run.","triggerScenarios":"Running 'sd library sync' (interactive setup) on a device whose daemon has zero entries in its pairing database. The query is execute_core_query!(ctx, ListPairedDevicesInput { connected_only: false }), so even offline paired devices count; empty means nothing was ever paired.","commonSituations":"Fresh install before any pairing was done; the daemon data directory was reset or changed (pairings live in daemon state, not in the CLI); testing the wizard against a dev daemon with a clean state.","solutions":["Run 'sd network pair generate' on this device to create a pairing code","On the other device run 'sd network pair join <code>' with that code","Confirm the pairing took effect by listing paired devices before retrying 'sd library sync'","If pairing was done previously, verify the daemon is running against the expected data directory (pairing records are stored there)"],"exampleFix":"// before: wizard discovers empty pairing list and bails mid-flow\nif paired_devices.devices.is_empty() {\n    anyhow::bail!(\"No paired devices found. ...\");\n}\n\n// after: check pairing up-front so the user is told before answering prompts\nlet paired_devices: ListPairedDevicesOutput = execute_core_query!(\n    ctx,\n    ListPairedDevicesInput { connected_only: false }\n);\nif paired_devices.devices.is_empty() {\n    println!(\"No paired devices found. Pair one first:\");\n    println!(\"  sd network pair generate\");\n    return Ok(()); // graceful exit instead of hard bail\n}","handlingStrategy":"validation","validationCode":"// Before launching the wizard, ask the daemon for paired devices\nlet paired: ListPairedDevicesOutput = execute_core_query!(\n    ctx,\n    ListPairedDevicesInput { connected_only: false }\n);\nif paired.devices.is_empty() {\n    eprintln!(\"Pair a device first: sd network pair generate / sd network pair join <code>\");\n    return Ok(());\n}","typeGuard":"fn has_paired_devices(out: &ListPairedDevicesOutput) -> bool {\n    !out.devices.is_empty()\n}","tryCatchPattern":"match run_sync_wizard(ctx).await {\n    Err(e) if e.to_string().contains(\"No paired devices\") => {\n        eprintln!(\"Skipping sync: {}\", e);\n        Ok(())\n    }\n    other => other,\n}","preventionTips":["Pair devices immediately after install so the wizard never starts from an empty list","In automation, pre-flight the paired-device query before entering interactive prompts","Remember pairing state lives in the daemon's data directory - changing it invalidates pairings"],"tags":["cli","network","pairing","sync","interactive"],"backgroundTag":null,"analyzedSha":"6dfeccf2113039e35f2ce735f945e70dc3e4ea45","analyzedAt":"2026-08-16T11:26:17.074Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}