astrid-runtime/astrid · error
legacy env/secret status exceeds the bounded principal limit
Error message
legacy env/secret status exceeds the bounded principal limit ({MAX_PRINCIPALS_PER_PASS}) What it means
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.
Source
Thrown at crates/astrid-capsule-install/src/storage/migration.rs:305
pub alias: PrincipalId,
/// Whether the legacy per-principal env directory still has entries.
pub native_env_present: bool,
/// Whether the legacy per-principal secret root still has entries.
pub native_secret_present: bool,
/// Durable capsule scopes that do not carry a completed import receipt.
pub unreceipted_capsules: Vec<String>,
}
/// Inspect legacy env/secret retirement completeness for every admitted UID.
pub async fn legacy_env_secret_import_status(
store: &RuntimePrincipalStore,
home: &astrid_core::dirs::AstridHome,
directory: &astrid_storage::PrincipalDirectory,
) -> anyhow::Result<Vec<LegacyEnvSecretImportStatus>> {
const MAX_PRINCIPALS_PER_PASS: usize = 4096;
let bindings = directory.bindings();
if bindings.len() > MAX_PRINCIPALS_PER_PASS {
bail!(
"legacy env/secret status exceeds the bounded principal limit ({MAX_PRINCIPALS_PER_PASS})"
);
}
let mut statuses = Vec::with_capacity(bindings.len());
for (alias, uid) in bindings {
let principal_home = home.principal_home(&alias);
astrid_core::platform_fs::verify_no_redirects(principal_home.root())
.with_context(|| format!("verify legacy principal root for {alias}"))?;
let native_env_present = legacy_entries_present(&principal_home.env_dir())?;
let native_secret_present =
legacy_entries_present(&home.secrets_dir().join(alias.as_str()))?;
let owner = StateOwner::Principal(uid);
let mut unreceipted_capsules = Vec::new();
for summary in store.capsules().list(&owner)? {
let scope = astrid_storage::env::principal_env_store(store.kv(), uid, summary.id())?;
if scope
.get(astrid_storage::env::LEGACY_IMPORT_MARKER_KEY)
.await?View on GitHub (pinned to affd8760f4)
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.
Example fix
// before
import_env_and_secrets(&home, &directory)?; // bails with >4096 bindings
// after: prune first
if directory.bindings().len() > 4096 {
prune_unused_principals(&directory)?;
}
import_env_and_secrets(&home, &directory)?; Defensive patterns
Strategy: validation
Validate before calling
if directory.bindings().len() > 4096 {
eprintln!("principal directory too large for one env/secret import pass");
} Type guard
fn importable(directory: &astrid_storage::PrincipalDirectory) -> bool {
directory.bindings().len() <= 4096
} Try / catch
match import_env_and_secrets(&home, &directory) {
Ok(statuses) => { /* ... */ }
Err(e) if e.to_string().contains("bounded principal limit") => {
eprintln!("split principals into batches of ≤4096 and import per batch");
}
Err(e) => return Err(e),
} Prevention
- 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.
When it happens
Trigger: Calling import_env_and_secrets (which calls legacy_env_secret_import_status) when directory.bindings() returns more than 4096 principals.
Common situations: Bulk imports that created thousands of principals; legacy home directories shared across many projects/users; scripted mass-registration of aliases before import.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- legacy capsule migration exceeds the bounded principal limit
- --capsule is required; native default env storage was retire
- legacy secret source reappeared after completed migration: {
- cannot retire leftover capsule authority while pending trans
- cannot retire leftover capsule authority while previous tran
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/b9e2bc0bb53de547.
Report an issue: GitHub.