{"record":{"id":"40feaf57d0ff18cd","repo":"astrid-runtime/astrid","slug":"mount-was-issued-to-another-acting-principal-40feaf","errorCode":null,"errorMessage":"mount was issued to another acting principal","messagePattern":"mount was issued to another acting principal","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage-provider-winfsp/src/main.rs","lineNumber":272,"sourceCode":") {\n    let _ = client\n        .request(AdminRequestKind::StorageMountRevoke {\n            mount_id: lease.mount_id,\n        })\n        .await;\n    if auto_created {\n        let _ = std::fs::remove_dir(mountpoint);\n    }\n}\n\nasync fn unmount(\n    client: &mut AdminClient,\n    acting_principal: &PrincipalId,\n    selector: &StorageMountSelectorV1,\n) -> Result<StorageProviderSuccessV1> {\n    let record = resolve_record(selector)?;\n    if &record.requested_by != acting_principal {\n        bail!(\"mount was issued to another acting principal\");\n    }\n    let lease_is_live = unmount_status(\n        client\n            .request(AdminRequestKind::StorageMountStatus {\n                mount_id: record.mount_id,\n            })\n            .await?,\n    )?;\n    native_unmount(&record.control_path).await?;\n    if lease_is_live {\n        into_success(\n            client\n                .request(AdminRequestKind::StorageMountRevoke {\n                    mount_id: record.mount_id,\n                })\n                .await?,\n        )?;\n    }","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-provider-winfsp/src/main.rs#L254-L290","documentation":"unmount() resolves the mount record for the selector and compares its requested_by principal against the acting principal. Only the principal that originally requested the mount may unmount it; any other caller is rejected.","triggerScenarios":"Calling execute(unmount) with an acting_principal that differs from the requested_by recorded on the resolved StorageMountSelectorV1 record — e.g. an admin or another service account attempting to tear down a mount owned by a different user.","commonSituations":"Running the unmount under a different service account or user than the one that mounted; credential/identity changes between mount and unmount (re-login, switched principal IDs); scripts assuming any local admin can unmount.","solutions":["Re-run the unmount as the same principal recorded in the mount record's requested_by field.","Have the owning principal unmount, or re-issue the mount under the intended principal.","Check which principal created the mount (via mount status/admin API) before attempting teardown.","Fix scripts/tests that hardcode a different principal than the mounting one."],"exampleFix":"// before: teardown under the wrong principal\nunmount(client, &other_principal, &selector).await?;\n// after: use the recorded owner\nlet record = resolve_record(&selector)?;\nunmount(client, &record.requested_by, &selector).await?;","handlingStrategy":"validation","validationCode":"// Before unmounting, confirm ownership:\nlet record = resolve_record(&selector)?;\nif &record.requested_by != acting_principal {\n    return Err(anyhow!(\"only {} may unmount this mount\", record.requested_by));\n}","typeGuard":"// Rust\nfn can_unmount(record: &MountRecord, principal: &PrincipalId) -> bool {\n    &record.requested_by == principal\n}","tryCatchPattern":"// Caller\nmatch unmount(client, principal, &selector).await {\n    Err(e) if e.to_string().contains(\"issued to another acting principal\") => {\n        // switch to the owning principal or ask the owner to unmount\n    }\n    other => other?,\n}","preventionTips":["Track which principal created each mount and use it for teardown","Avoid switching service accounts/identities between mount and unmount","Query mount status (record.requested_by) before automated teardown"],"tags":["winfsp","authorization","mount","principal"],"backgroundTag":"permission-denied","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"}