{"record":{"id":"71f7fe41a868c007","repo":"astrid-runtime/astrid","slug":"legacy-capsule-migration-exceeds-the-bounded-princ","errorCode":null,"errorMessage":"legacy capsule migration exceeds the bounded principal limit ({MAX_PRINCIPALS_PER_PASS})","messagePattern":"legacy capsule migration exceeds the bounded principal limit \\((.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-capsule-install/src/storage/migration.rs","lineNumber":265,"sourceCode":"            .entry(receipt.uid)\n            .or_default()\n            .push(receipt.capsule_id);\n    }\n    Ok(migrated.into_iter().collect())\n}\n\n/// Import legacy capsule directories for every admitted principal and return\n/// a canonical authority-retirement proof for the barrier ledger.\npub fn migrate_all_native_capsules_with_report(\n    store: &Arc<RuntimePrincipalStore>,\n    home: &astrid_core::dirs::AstridHome,\n    directory: &astrid_storage::PrincipalDirectory,\n    workspace_targets: &[std::path::PathBuf],\n) -> anyhow::Result<LegacyCapsuleMigrationReport> {\n    const MAX_PRINCIPALS_PER_PASS: usize = 4096;\n    let bindings = directory.bindings();\n    if bindings.len() > MAX_PRINCIPALS_PER_PASS {\n        bail!(\n            \"legacy capsule migration exceeds the bounded principal limit ({MAX_PRINCIPALS_PER_PASS})\"\n        );\n    }\n    let mut report = LegacyCapsuleMigrationReport::default();\n    for (alias, _uid) in bindings {\n        let principal_report =\n            migrate_native_capsules_with_report(store, home, &alias, workspace_targets)?;\n        report\n            .retired_authorities\n            .extend(principal_report.retired_authorities);\n    }\n    report.retired_authorities.sort();\n    Ok(report)\n}\n\n/// Receipt status for one admitted principal's legacy env/secret boundary.\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct LegacyEnvSecretImportStatus {","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-capsule-install/src/storage/migration.rs#L247-L283","documentation":"Legacy capsule migration processes principals in bounded passes and hard-caps a single pass at MAX_PRINCIPALS_PER_PASS = 4096 bindings. If the principal directory contains more than 4096 aliases, the migration refuses to run rather than perform an unbounded loop that could take unbounded time or memory. This is a deliberate safety bound, not a corruption indicator.","triggerScenarios":"Calling migrate_all_native_capsules or migrate_legacy_layout when directory.bindings() returns more than 4096 entries.","commonSituations":"Very large or long-lived legacy installs with thousands of principal aliases; directories accumulated junk aliases over years; a test or script created thousands of principals.","solutions":["Reduce the number of principals in the directory before migrating (archive or delete unused aliases).","Split the principal directory into batches and migrate each batch against a directory view containing at most 4096 bindings.","Raise MAX_PRINCIPALS_PER_PASS in a patched build if your workload genuinely needs larger passes (accepting longer migration runs).","Contact maintainers if you need chunked migration support upstream."],"exampleFix":"// before\nmigrate_all_native_capsules(&home, &directory)?; // bails with >4096 bindings\n\n// after: prune unused bindings first\nlet bindings: Vec<_> = directory.bindings().into_iter().collect();\nassert!(bindings.len() <= 4096, \"prune principals before migrating\");\nmigrate_all_native_capsules(&home, &directory)?;","handlingStrategy":"validation","validationCode":"let count = directory.bindings().len();\nif count > 4096 {\n    return Err(anyhow::anyhow!(\n        \"{} principals exceed the 4096 per-pass migration limit; prune or batch first\", count));\n}","typeGuard":"fn within_pass_limit(bindings: &[(String, u64)]) -> bool {\n    bindings.len() <= 4096\n}","tryCatchPattern":"match migrate_all_native_capsules(&home, &directory) {\n    Ok(report) => { /* ... */ }\n    Err(e) if e.to_string().contains(\"bounded principal limit\") => {\n        eprintln!(\"too many principals: batch the migration\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Monitor principal-directory size; alert before it approaches 4096 bindings.","Prune stale/unused aliases as routine maintenance.","Design bulk principal creation with batching in mind.","Pin the astrid version you rely on if you patch MAX_PRINCIPALS_PER_PASS locally."],"tags":["migration","limit-exceeded","capsule","principal-directory"],"backgroundTag":"value-out-of-range","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}