Hmbown/CodeWhale · error · io::Error
Codewhale-owned credential file owner is not the current…
Error message
Codewhale-owned credential file owner is not the current user
What it means
verify_windows_owner_only_handle retrieves the security descriptor of the opened credential handle and requires the file's owner SID to equal the current user's SID (via EqualSid). It throws PermissionDenied when the owner is null or a different account, ensuring the Codewhale-owned credential is not owned by another principal such as Administrator, SYSTEM, or another user.
Solutions
- Take ownership as the current user: `takeown /F <file>` then `icacls <file> /setowner %USERNAME%`, or reset ownership in the Security tab (Advanced → Owner).
- Recreate the file while running as the normal (non-elevated) user so it inherits correct ownership.
- If the app should run under a service account, create the credential under that account instead of copying it across accounts.
- Avoid provisioning credential files from elevated installers without fixing ownership afterwards.
Example fix
:: before (run as admin) copy D:\secrets\token.json C:\Users\me\.codewhale\token.json :: owner = Administrators :: after takeown /F C:\Users\me\.codewhale\token.json icacls C:\Users\me\.codewhale\token.json /setowner %USERNAME%
Defensive patterns
Strategy: validation
Validate before calling
// PowerShell pre-check: // (Get-Acl $path).Owner -eq [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
Try / catch
match read_codewhale_owned_to_string(&path) {
Ok(creds) => use(creds),
Err(e) if e.to_string().contains("owner is not the current user") => {
eprintln!("fix owner: takeown /F {p} && icacls {p} /setowner %USERNAME%", p = path.display());
}
Err(e) => return Err(e),
} Prevention
- Provision credential files as the same user that will run the app, not from elevated installers.
- After copying/restoring, reset ownership to the current user.
- Verify owner with (Get-Acl $file).Owner before first use.
- Never share credential files across user accounts by copy.
When it happens
Trigger: read_codewhale_owned_to_string opens a file owned by a different account — e.g. created by an elevated installer running as Administrator, copied by another user, or restored from a backup preserving foreign ownership.
Common situations: Credential file provisioned by a setup script run with elevation, leaving Administrator/SYSTEM as owner; file copied from another machine/user profile; migration tool reset ownership; running the app under a different account than the one that created the file.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Codewhale-owned credential file DACL must grant only one…
- Codewhale-owned credential file must have an owner-only DACL
- Codewhale-owned xAI OAuth storage owner is not the current…
- Codewhale issue-report DACL is not current-user-only
- Codewhale issue-report DACL must grant only one user
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/23845c18ff20c2f0.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/external_credentials.rs:469
let result = unsafe {
GetSecurityInfo(
handle,
SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
&mut owner,
std::ptr::null_mut(),
&mut dacl,
std::ptr::null_mut(),
&mut descriptor,
)
};
if result != ERROR_SUCCESS {
return Err(io::Error::from_raw_os_error(result as i32));
}
let _descriptor = WindowsLocalAllocation(descriptor.cast());
// SAFETY: `owner` is non-null; `user.sid()` is owned by `user`.
if owner.is_null() || unsafe { EqualSid(owner, user.sid()) } == 0 {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
"Codewhale-owned credential file owner is not the current user",
));
}
if dacl.is_null() {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
"Codewhale-owned credential file must have an owner-only DACL",
));
}
let mut count = 0;
let mut entries: *mut EXPLICIT_ACCESS_W = std::ptr::null_mut();
// SAFETY: `dacl` is owned by the live security descriptor; Windows
// allocates the returned entries, released below.
let result = unsafe { GetExplicitEntriesFromAclW(dacl, &mut count, &mut entries) };
if result != ERROR_SUCCESS {
return Err(io::Error::from_raw_os_error(result as i32));
}View on GitHub (pinned to 73e0f67d83)