{"record":{"id":"5009483c1a656dca","repo":"astrid-runtime/astrid","slug":"all-total-capsule-install-s-failed-not-writin","errorCode":null,"errorMessage":"all {total} capsule install(s) failed — not writing Distro.lock. Fix the errors above and re-run `astrid init`.","messagePattern":"all (.+?) capsule install\\(s\\) failed — not writing Distro\\.lock\\. Fix the errors above and re-run `astrid init`\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/init.rs","lineNumber":578,"sourceCode":"}\n\n/// Whether a provision run should persist a `Distro.lock`.\n///\n/// Only a FULL success (`succeeded == total`) or an empty selection\n/// (`total == 0`, nothing to install) writes a lock. A PARTIAL run writes\n/// NO lock. This keeps the outcome honest and ensures a retry still evaluates\n/// every member through the durable identity query instead of trusting a\n/// partial record. Because `install_capsule_batch` is idempotent, withholding\n/// the lock lets a re-run re-attempt missing capsules and converge to a full\n/// success, which then writes the lock.\n/// A wholly-failed run also writes no lock (and additionally bails non-zero).\nfn should_write_lock(total: usize, succeeded: usize) -> bool {\n    total == 0 || succeeded == total\n}\n\nfn reject_total_install_failure(total: usize, succeeded: usize) -> anyhow::Result<()> {\n    if total > 0 && succeeded == 0 {\n        bail!(\n            \"all {total} capsule install(s) failed — not writing Distro.lock. \\\n             Fix the errors above and re-run `astrid init`.\"\n        );\n    }\n    Ok(())\n}\n\n/// Persist `lock` at `lock_path` iff the run earned it (see\n/// [`should_write_lock`]). Returns whether the lock was written, so the\n/// caller can pick the honest completion message. Kept as a small helper so\n/// the \"partial run leaves no lock on disk\" invariant is unit-testable\n/// without a network install.\n#[cfg(test)]\nfn persist_lock_if_earned(\n    lock_path: &std::path::Path,\n    total: usize,\n    succeeded: usize,\n    lock: &DistroLock,","sourceCodeStart":560,"sourceCodeEnd":596,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/init.rs#L560-L596","documentation":"reject_total_install_failure aborts init when every requested capsule install failed (total > 0, succeeded == 0). In that case Distro.lock is intentionally not written, since locking a distro where nothing installed would be misleading; the user must fix the errors and retry.","triggerScenarios":"install flow reaches reject_total_install_failure with succeeded == 0 and total > 0 — e.g. all capsule installs failed due to network outage, bad distro manifest, or revoked source access.","commonSituations":"No network connectivity when the distro requires GitHub sources; GitHub auth expired/revoked for all private capsule repos; corrupt or wrong-version distro manifest.","solutions":["Fix the underlying cause shown in the per-capsule errors above (network, auth, source), then re-run `astrid init`.","If offline, obtain a .shuttle archive and install with --offline.","Verify the distro's capsule sources are reachable (git ls-remote / curl the raw URLs) before retrying."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if !Command::new(\"curl\").args([\"-sI\", \"https://raw.githubusercontent.com\"]).status()?.success() {\n    eprintln!(\"no network; use a .shuttle archive with --offline\");\n}","typeGuard":null,"tryCatchPattern":"let status = Command::new(\"astrid\").args([\"init\"]).status()?;\nif !status.success() {\n    eprintln!(\"install failed entirely; fix errors then rerun\");\n}","preventionTips":["Verify network/GitHub credentials before batch installs.","For air-gapped hosts, always use a .shuttle archive with --offline.","Read the per-capsule error output; the lockfile is intentionally not written on total failure."],"tags":["install","capsules","network","cli"],"backgroundTag":"incomplete-installation","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}