vercel/turborepo · error · std::io::Error

owner-only security descriptor did not contain a DACL

Error message

owner-only security descriptor did not contain a DACL

What it means

set_owner_only_dacl in endpoint.rs builds an owner-only DACL, applies it with SetNamedSecurityInfoW (DACL + PROTECTED_DACL), then reads the descriptor back with GetSecurityDescriptorDacl; this InvalidData error fires when the descriptor comes back with no DACL at all (dacl_present == 0 or null pointer). The ACL write did not stick, so the daemon aborts rather than run with unknown permissions.

Source

Thrown at crates/turborepo-daemon/src/endpoint.rs:287

        }
        let descriptor = LocalAllocGuard(descriptor as HLOCAL);

        let mut dacl_present = 0;
        let mut dacl_defaulted = 0;
        let mut dacl: *mut ACL = ptr::null_mut();
        if unsafe {
            GetSecurityDescriptorDacl(
                descriptor.0 as PSECURITY_DESCRIPTOR,
                &mut dacl_present,
                &mut dacl,
                &mut dacl_defaulted,
            )
        } == 0
        {
            return Err(std::io::Error::last_os_error());
        }
        if dacl_present == 0 || dacl.is_null() {
            return Err(std::io::Error::new(
                std::io::ErrorKind::InvalidData,
                "owner-only security descriptor did not contain a DACL",
            ));
        }

        let path = wide_null(path.as_std_path().as_os_str());
        let result = unsafe {
            SetNamedSecurityInfoW(
                path.as_ptr(),
                SE_FILE_OBJECT,
                DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
                ptr::null_mut(),
                ptr::null_mut(),
                dacl,
                ptr::null_mut(),
            )
        };
        if result == ERROR_SUCCESS {

View on GitHub (pinned to f9245100cf)

Solutions

  1. Point TEMP/TMP and any daemon path override at a local NTFS volume and restart the daemon
  2. Delete the daemon directory so it is recreated with fresh security descriptors
  3. If it persists on NTFS, report with the volume type and the path involved

Example fix

# cmd: move temp to a local NTFS drive
setx TEMP C:\Users\you\AppData\Local\Temp
setx TMP C:\Users\you\AppData\Local\Temp
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure temp/daemon paths live on NTFS before daemon start
fs::metadata(&tmp)?.filesystem_type_is_ntfs() // pseudo; check via GetVolumeInformationW

Try / catch

match secure_daemon_dir(path) {
    Err(e) if e.kind() == std::io::ErrorKind::InvalidData && e.to_string().contains("DACL") => {
        // move to a local NTFS path, then retry daemon start
    }
    other => other?,
}

Prevention

When it happens

Trigger: Daemon startup hardening on a volume/path that silently drops or ignores DACL protection — e.g. temp redirected to a FAT-formatted or network drive, or the descriptor being rewritten concurrently.

Common situations: TMP/TEMP overridden to a non-NTFS location (FAT USB stick, some SMB shares) Object IDs / quota states on the volume that reject PROTECTED_DACL writes

Related errors


AI-assisted analysis of vercel/turborepo@f9245100cf (2026-08-17). Data as JSON: /api/errors/36a26fd3f6704265. Report an issue: GitHub.