Hmbown/CodeWhale · error · io::Error
Codewhale-owned credential file must have an owner-only DACL
Error message
Codewhale-owned credential file must have an owner-only DACL
What it means
After confirming the owner, verify_windows_owner_only_handle requires the file to have a discretionary ACL (DACL) at all. A null DACL means access is governed by inherit-only rules or (in the SE_DACL_PRESENT-less case) that everyone may access the object; the library throws PermissionDenied because an owner-only guarantee cannot be verified without an explicit DACL.
Solutions
- Set an explicit owner-only DACL: `icacls <file> /inheritance:r /grant:r "%USERNAME%:F"`.
- Recreate the file in place so Windows assigns a default secure DACL.
- Verify with `icacls <file>` that an explicit ACL listing only your user exists.
- Avoid moving credential files from non-ACL filesystems without resetting permissions.
Example fix
:: before icacls C:\Users\me\.codewhale\token.json :: No DACL / inherited nothing :: after icacls C:\Users\me\.codewhale\token.json /inheritance:r /grant:r "%USERNAME%:F"
Defensive patterns
Strategy: validation
Validate before calling
// PowerShell pre-check: an explicit DACL must exist // $acl = Get-Acl $path; $acl.GetAccessRules($true, $false, [System.Security.Principal.SecurityIdentifier]).Count -ge 1
Try / catch
match read_codewhale_owned_to_string(&path) {
Ok(creds) => use(creds),
Err(e) if e.to_string().contains("owner-only DACL") => {
eprintln!("set explicit ACL: icacls {p} /inheritance:r /grant:r %USERNAME%:F", p = path.display());
}
Err(e) => return Err(e),
} Prevention
- Always set an explicit ACL on credential files: icacls <file> /inheritance:r /grant:r "%USERNAME%:F".
- Do not move credential files from FAT/exFAT (no ACLs) without resetting permissions.
- Check ACLs survive backup/restore cycles; restore tools can drop descriptors.
- Verify with `icacls <file>` that explicit rules exist before first use.
When it happens
Trigger: read_codewhale_owned_to_string opens a credential file whose security descriptor has no DACL / a null DACL — e.g. the ACL was stripped, the file was created on a filesystem without ACL enforcement and later moved, or `icacls /reset` removed explicit entries.
Common situations: File copied from a FAT/exFAT volume (no ACLs) to NTFS; a backup/restore tool dropped the security descriptor; `icacls <file> /remove` removed all ACEs; file was created in a directory whose inheritance produced no explicit DACL.
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 owner is not the current…
- Codewhale-owned xAI OAuth DACL must grant only one user
- Codewhale-owned xAI OAuth storage must have an owner-only…
- Codewhale issue-report DACL is not current-user-only
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/d060ed8f98314ec1.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/external_credentials.rs:475
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));
}
let _entries = WindowsLocalAllocation(entries.cast());
if count != 1 || entries.is_null() {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
"Codewhale-owned credential file DACL must grant only one user",
));View on GitHub (pinned to 73e0f67d83)