QL-Win/QuickLook · error · UnauthorizedAccessException

{folder} is not writable.

Error message

{folder} is not writable.

What it means

Thrown by FileHelper.CreateTempFile when NativeMethods.Kernel32.CreateFile returns an invalid handle (INVALID_HANDLE_VALUE) for the target path under {folder}. Despite the UnauthorizedAccessException type, the real Win32 cause can be access denied, path-not-found, invalid path characters, or disk full — the code never calls Marshal.GetLastWin32Error to disambiguate. The interpolated message names only the folder, not the file or the underlying error code.

Source

Thrown at QuickLook.Common/Helpers/FileHelper.cs:63

    public static string CreateTempFile(string folder, string filename = null)
    {
        if (string.IsNullOrWhiteSpace(filename))
            filename = Guid.NewGuid() + ".tmp";
        var fullPath = Path.Combine(folder, filename);

        var handle = new SafeFileHandle(IntPtr.Zero, true);

        try
        {
            Directory.CreateDirectory(folder);

            handle = NativeMethods.Kernel32.CreateFile(fullPath, FileAccess.ReadWrite,
                FileShare.None,
                IntPtr.Zero, FileMode.Create, FileAttributes.Temporary, IntPtr.Zero);

            if (handle.IsInvalid)
                throw new UnauthorizedAccessException($"{folder} is not writable.");

            return fullPath;
        }
        finally
        {
            if (!handle.IsInvalid && !handle.IsClosed)
                handle.Close();
        }
    }

    public static bool GetAssocApplication(string path, out string appFriendlyName)
    {
        appFriendlyName = string.Empty;
        var ext = Path.GetExtension(path).ToLower();

        // no assoc. app. found
        if (string.IsNullOrEmpty(GetAssocApplicationNative(ext, AssocStr.Command)))
            if (string.IsNullOrEmpty(GetAssocApplicationNative(ext, AssocStr.AppId))) // UWP

View on GitHub (pinned to cb5d9c429c)

Solutions

  1. Verify the folder is writable by the current process (Directory.CreateDirectory then attempt a test write) before calling CreateTempFile.
  2. Call Marshal.GetLastWin32Error right after CreateFile to surface the real Win32 error code and map it to a precise message.
  3. Fall back to Path.GetTempPath() (the system %TEMP%) when the supplied folder is not writable.
  4. Ensure the folder path stays under MAX_PATH or enable long-path support; sanitize filename for invalid characters.
  5. Check available disk space on the target drive before creating temp files.

Example fix

// before
handle = NativeMethods.Kernel32.CreateFile(fullPath, FileAccess.ReadWrite,
    FileShare.None, IntPtr.Zero, FileMode.Create, FileAttributes.Temporary, IntPtr.Zero);
if (handle.IsInvalid)
    throw new UnauthorizedAccessException($"{folder} is not writable.");

// after
handle = NativeMethods.Kernel32.CreateFile(fullPath, FileAccess.ReadWrite,
    FileShare.None, IntPtr.Zero, FileMode.Create, FileAttributes.Temporary, IntPtr.Zero);
if (handle.IsInvalid)
{
    int err = Marshal.GetLastWin32Error();
    throw new UnauthorizedAccessException(
        $"{folder} is not writable (Win32 error {err}: {new System.ComponentModel.Win32Exception(err).Message}).");
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate the folder is writable before calling CreateTempFile.
public static bool IsFolderWritable(string folder)
{
    try
    {
        Directory.CreateDirectory(folder);
        string probe = Path.Combine(folder, $".writeprobe_{Guid.NewGuid():N}");
        File.WriteAllText(probe, "x");
        File.Delete(probe);
        return true;
    }
    catch { return false; }
}

Try / catch

try { var path = FileHelper.CreateTempFile(folder); }
catch (UnauthorizedAccessException ex)
{
    // folder lacks write permission or CreateFile failed;
    // fall back to system temp: Path.GetTempPath()
    logger.Warn(ex, $"Folder {folder} not writable, using system temp.");
    path = FileHelper.CreateTempFile(Path.GetTempPath());
}

Prevention

When it happens

Trigger: Calling FileHelper.CreateTempFile(folder, filename) where CreateFile with FileMode.Create / FileAttributes.Temporary fails: folder is on read-only media, the process lacks write ACL on the directory, the path exceeds MAX_PATH, an antivirus blocks creation, or the disk is full.

Common situations: QuickLook runs under a restricted context (e.g. preview hosted by explorer.exe or a low-integrity process); the temp folder is redirected to a protected location; a group policy locks down %TEMP%; a path with Unicode or very long segments exceeds 260 chars; AV/EDR hooks block the CreateFile call.

Related errors


AI-assisted analysis of QL-Win/QuickLook@cb5d9c429c (2026-08-13). Data as JSON: /api/errors/f23592137f56b4b7. Report an issue: GitHub.