{"record":{"id":"0e863a90f5e38788","repo":"astrid-runtime/astrid","slug":"mount-was-issued-to-another-acting-principal","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-fuse/src/main.rs","lineNumber":416,"sourceCode":"            bail!(\"FUSE service status failed [{code}]: {message}\")\n        },\n    }\n    Ok(StorageProviderSuccessV1::Status {\n        mount_id: record.mount_id,\n        mountpoint: record.mountpoint,\n        access: record.access,\n        dirty: lease_status.dirty,\n    })\n}\n\nasync fn unmount(\n    client: &mut AdminClient,\n    acting_principal: &astrid_core::PrincipalId,\n    selector: &StorageMountSelectorV1,\n) -> Result<StorageProviderSuccessV1> {\n    let record = registry::resolve_record(selector)?;\n    if &record.requested_by != acting_principal {\n        bail!(\"mount was issued to another acting principal\");\n    }\n    let live = if let Some(status) = kernel_lease_status(client, &record.mount_id).await? {\n        if status.mountpoint != record.mountpoint || status.access != record.access {\n            bail!(\"kernel lease metadata does not match the FUSE provider registry\");\n        }\n        true\n    } else {\n        cleanup_stale_record(client, acting_principal, &record).await?;\n        false\n    };\n    if live {\n        let control_result = control_unmount(&record.control_path, acting_principal);\n        if let Err(error) = control_result {\n            eprintln!(\n                \"falling back to stale FUSE cleanup after control unmount failure: {error:#}\"\n            );\n            cleanup_stale_record(client, acting_principal, &record).await?;\n        } else {","sourceCodeStart":398,"sourceCodeEnd":434,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-provider-fuse/src/main.rs#L398-L434","documentation":"Raised by the `unmount` command (crates/astrid-storage-provider-fuse/src/main.rs:416). The registry record for the selected mount stores the `requested_by` principal that originally issued the mount; if the acting principal performing the unmount differs from that owner, the provider refuses. This is a single-owner guard preventing one principal from tearing down another principal's mount.","triggerScenarios":"Calling `unmount` with a StorageMountSelectorV1 whose resolved record has `record.requested_by != acting_principal` — i.e. a different admin principal identity than the one that created the mount.","commonSituations":"Team environments where a second operator tries to unmount a colleague's mount; running the CLI under a different account/service identity than the one that mounted; automation credentials rotated so the new principal no longer matches the recorded owner; copied registry records retaining the original owner.","solutions":["Run the unmount under the same principal that originally issued the mount (check `record.requested_by`).","If ownership must transfer, have the original owner unmount, then re-mount under the new principal.","If the original principal is gone, remove the stale registry record via the cleanup path (stale-record cleanup) and re-create the mount under the current principal.","Verify the CLI's authenticated identity/credentials match the expected owner before retrying."],"exampleFix":"// before: unmounting with the wrong principal\nlet p = PrincipalId::from(\"svc-backup\");\nprovider.unmount(&p, &selector).await?; // panics with 'issued to another acting principal'\n// after: use the owning principal\nlet owner = registry_record(&selector)?.requested_by;\nprovider.unmount(&owner, &selector).await?;","handlingStrategy":"validation","validationCode":"// verify ownership before attempting unmount\nlet record = registry::resolve_record(&selector)?;\nif &record.requested_by != &acting_principal {\n    return Err(format!(\n        \"mount {} owned by {:?}; current principal {:?} cannot unmount\",\n        record.mount_id, record.requested_by, acting_principal\n    ).into());\n}","typeGuard":"fn is_mount_owner(record: &MountRecord, principal: &astrid_core::PrincipalId) -> bool {\n    &record.requested_by == principal\n}","tryCatchPattern":"match provider.unmount(&principal, &selector).await {\n    Err(e) if e.to_string().contains(\"issued to another acting principal\") => {\n        // fall back to the recorded owner\n        let owner = registry::resolve_record(&selector)?.requested_by;\n        provider.unmount(&owner, &selector).await\n    }\n    other => other,\n}","preventionTips":["Record which principal issued each mount and use that identity for teardown.","Avoid rotating automation credentials without re-issuing mounts under the new principal.","Implement an ownership-transfer flow (unmount + remount) instead of cross-principal unmounts.","Clean up registry records belonging to decommissioned principals."],"tags":["permissions","ownership","fuse","mount"],"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"}