Hmbown/CodeWhale · error

Codewhale credentials directory must be owned by the…

Error message

Codewhale credentials directory must be owned by the current user

What it means

The credentials directory must be owned by the effective UID of the running process. This is a hardening check against credential theft via another account's directory; the store also force-sets 0o700 permissions after the check. Opening the store fails if the directory owner differs from geteuid().

Solutions

  1. Chown the directory back to the current user: `sudo chown -R $(id -u):$(id -g) ~/.codewhale`.
  2. Avoid running the tool with sudo; re-authenticate as the normal user.
  3. In containers, create the directory as the runtime USER before the first run.
  4. If a pre-provisioned directory is required, create it with the same UID that runs the app.

Example fix

// shell fix
# sudo chown -R $(id -u):$(id -g) ~/.codewhale
// guard before calling open
let md = std::fs::metadata(dir)?;
anyhow::ensure!(md.uid() == unsafe { libc::geteuid() }, "dir not owned by current user");
Defensive patterns

Strategy: validation

Validate before calling

#[cfg(unix)]
fn owned_by_current_user(dir: &Path) -> bool {
    std::os::unix::fs::MetadataExt::uid(&std::fs::metadata(dir).unwrap())
        == unsafe { libc::geteuid() }
}

Try / catch

match XaiOAuthCredentialStore::open(dir) {
    Ok(s) => s,
    Err(e) if e.to_string().contains("owned by the current user") => {
        // instruct user to chown or re-run without sudo
        bail!("fix ownership: sudo chown -R $(id -u):$(id -g) {}", dir.display());
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling open when the credentials directory is owned by root or another user — e.g. a previous run used sudo, or the directory was created by a system package/installer.

Common situations: Running the CLI once with sudo created a root-owned ~/.codewhale; a Docker container copied the directory as root; an admin pre-created the directory.

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


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/e26ed09e9c68bc01. Report an issue: GitHub.

Appendix: source

Thrown at crates/config/src/xai_credentials.rs:672

                    crate::quote_os_path(directory)
                )
            });
        }
        // SAFETY: `fd` is a newly owned descriptor on the success path above.
        current = unsafe { File::from_raw_fd(fd) };
    }
    let metadata = current.metadata().with_context(|| {
        format!(
            "inspecting Codewhale credentials directory {}",
            crate::quote_os_path(directory)
        )
    })?;
    anyhow::ensure!(
        metadata.is_dir(),
        "Codewhale credentials path must be a directory"
    );
    // SAFETY: geteuid(2) dereferences no pointers.
    anyhow::ensure!(
        metadata.uid() == unsafe { libc::geteuid() },
        "Codewhale credentials directory must be owned by the current user"
    );
    current
        .set_permissions(fs::Permissions::from_mode(0o700))
        .with_context(|| {
            format!(
                "securing Codewhale credentials directory {}",
                crate::quote_os_path(directory)
            )
        })?;
    Ok(XaiOAuthCredentialStore {
        directory: directory.to_path_buf(),
        directory_handle: current,
    })
}

#[cfg(unix)]

View on GitHub (pinned to 73e0f67d83)