{"record":{"id":"b9e2bc0bb53de547","repo":"astrid-runtime/astrid","slug":"legacy-env-secret-status-exceeds-the-bounded-princ","errorCode":null,"errorMessage":"legacy env/secret status exceeds the bounded principal limit ({MAX_PRINCIPALS_PER_PASS})","messagePattern":"legacy env/secret status exceeds the bounded principal limit \\((.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-capsule-install/src/storage/migration.rs","lineNumber":305,"sourceCode":"    pub alias: PrincipalId,\n    /// Whether the legacy per-principal env directory still has entries.\n    pub native_env_present: bool,\n    /// Whether the legacy per-principal secret root still has entries.\n    pub native_secret_present: bool,\n    /// Durable capsule scopes that do not carry a completed import receipt.\n    pub unreceipted_capsules: Vec<String>,\n}\n\n/// Inspect legacy env/secret retirement completeness for every admitted UID.\npub async fn legacy_env_secret_import_status(\n    store: &RuntimePrincipalStore,\n    home: &astrid_core::dirs::AstridHome,\n    directory: &astrid_storage::PrincipalDirectory,\n) -> anyhow::Result<Vec<LegacyEnvSecretImportStatus>> {\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 env/secret status exceeds the bounded principal limit ({MAX_PRINCIPALS_PER_PASS})\"\n        );\n    }\n    let mut statuses = Vec::with_capacity(bindings.len());\n    for (alias, uid) in bindings {\n        let principal_home = home.principal_home(&alias);\n        astrid_core::platform_fs::verify_no_redirects(principal_home.root())\n            .with_context(|| format!(\"verify legacy principal root for {alias}\"))?;\n        let native_env_present = legacy_entries_present(&principal_home.env_dir())?;\n        let native_secret_present =\n            legacy_entries_present(&home.secrets_dir().join(alias.as_str()))?;\n        let owner = StateOwner::Principal(uid);\n        let mut unreceipted_capsules = Vec::new();\n        for summary in store.capsules().list(&owner)? {\n            let scope = astrid_storage::env::principal_env_store(store.kv(), uid, summary.id())?;\n            if scope\n                .get(astrid_storage::env::LEGACY_IMPORT_MARKER_KEY)\n                .await?","sourceCodeStart":287,"sourceCodeEnd":323,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-capsule-install/src/storage/migration.rs#L287-L323","documentation":"legacy_env_secret_import_status computes per-principal import status for legacy env/secret data and, like migration, bounds a single pass to MAX_PRINCIPALS_PER_PASS = 4096 bindings. If the principal directory holds more than 4096 aliases, status computation is refused instead of fanning out an unbounded number of filesystem scans. Called from import_env_and_secrets.","triggerScenarios":"Calling import_env_and_secrets (which calls legacy_env_secret_import_status) when directory.bindings() returns more than 4096 principals.","commonSituations":"Bulk imports that created thousands of principals; legacy home directories shared across many projects/users; scripted mass-registration of aliases before import.","solutions":["Prune or archive unused principals so the directory has at most 4096 bindings.","Import env/secret data in batches: split principals into groups of ≤4096 and call import per group.","Patch MAX_PRINCIPALS_PER_PASS upward if your deployment legitimately exceeds the bound."],"exampleFix":"// before\nimport_env_and_secrets(&home, &directory)?; // bails with >4096 bindings\n\n// after: prune first\nif directory.bindings().len() > 4096 {\n    prune_unused_principals(&directory)?;\n}\nimport_env_and_secrets(&home, &directory)?;","handlingStrategy":"validation","validationCode":"if directory.bindings().len() > 4096 {\n    eprintln!(\"principal directory too large for one env/secret import pass\");\n}","typeGuard":"fn importable(directory: &astrid_storage::PrincipalDirectory) -> bool {\n    directory.bindings().len() <= 4096\n}","tryCatchPattern":"match import_env_and_secrets(&home, &directory) {\n    Ok(statuses) => { /* ... */ }\n    Err(e) if e.to_string().contains(\"bounded principal limit\") => {\n        eprintln!(\"split principals into batches of ≤4096 and import per batch\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Keep principal counts per home directory below the 4096 bound.","Batch bulk imports explicitly instead of registering all principals at once.","Prune legacy aliases before import.","Add a pre-import size check to your deployment scripts."],"tags":["migration","limit-exceeded","env","secrets","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"}