peass-ng/PEASS-ng · error · ArgumentException

Resources.Cannot_Create_Directory

Error message

Resources.Cannot_Create_Directory

What it means

AlphaFS's ConstructFullPath helper validates that a path can serve as a directory root. When the trimmed path is exactly a drive-like two characters ('C:' with a drive-letter/vertical-slash character at index 1), it throws ArgumentException(Resources.Cannot_Create_Directory, 'path') because creating a directory at a bare drive specifier is meaningless. This surfaces when CreateDirectoryCore tries to construct the full path of directories to create.

Source

Thrown at winPEAS/winPEASexe/winPEAS/3rdParty/AlphaFS/Filesystem/Directory Class/Directory Core Methods/Directory.CreateDirectoryCore.cs:182

            // We are not always interested in a new DirectoryInfo instance.

            return returnNull ? null : new DirectoryInfo(transaction, longPath, PathFormat.LongFullPath);
         }
      }


      private static Stack<string> ConstructFullPath(KernelTransaction transaction, string path)
      {
         var longPathPrefix = Path.IsUncPathCore(path, false, false) ? Path.LongPathUncPrefix : Path.LongPathPrefix;
         path = Path.GetRegularPathCore(path, GetFullPathOptions.None, false);

         var length = path.Length;
         if (length >= 2 && Path.IsDVsc(path[length - 1], false))
            --length;

         var rootLength = Path.GetRootLength(path, false);
         if (length == 2 && Path.IsDVsc(path[1], false))
            throw new ArgumentException(Resources.Cannot_Create_Directory, "path");


         // Check if directories are missing.
         var list = new Stack<string>(100);

         if (length > rootLength)
         {
            for (var index = length - 1; index >= rootLength; --index)
            {
               var path1 = path.Substring(0, index + 1);
               var path2 = longPathPrefix + path1.TrimStart('\\');

               if (!File.ExistsCore(transaction, true, path2, PathFormat.LongFullPath))
                  list.Push(path2);

               while (index > rootLength && !Path.IsDVsc(path[index], false))
                  --index;
            }

View on GitHub (pinned to 53fb989abc)

Solutions

  1. Pass a real directory path with at least one folder component, e.g. "C:\\Temp" instead of "C:".
  2. If you need the drive root, use "C:\\" (drive + separator) — the guard only rejects the bare 2-char form — or better, create a named folder on it.
  3. If the input is a root from Path.GetPathRoot and creation is pointless, short-circuit: skip CreateDirectory when path equals its own root.
  4. Append a default subdirectory when the resolved path has no folder part: if (Path.GetDirectoryName(p) == null) p = Path.Combine(p, "app").

Example fix

// before
Directory.CreateDirectory(Path.GetPathRoot(target)); // "C:"
// after
var root = Path.GetPathRoot(target);
var dir = Path.Combine(root, "myapp");
Directory.CreateDirectory(dir);
Defensive patterns

Strategy: validation

Validate before calling

static void EnsureNotBareDrive(string path)
{
    if (!string.IsNullOrEmpty(path) && path.Length == 2 && path[1] == ':')
        throw new ArgumentException($"'{path}' is a bare drive; provide a folder path");
}
EnsureNotBareDrive(path);
Directory.CreateDirectory(path);

Type guard

static bool IsBareDrivePath(string p) =>
    p != null && p.Length == 2 && char.IsLetter(p[0]) && p[1] == ':';

Try / catch

try
{
    Directory.CreateDirectory(path);
}
catch (ArgumentException ex) when (ex.ParamName == "path")
{
    // bare drive specifier like "C:" cannot be created
    logger.LogWarning("Refusing to create directory at bare drive: {Path}", path);
}

Prevention

When it happens

Trigger: Calling Directory.CreateDirectory with a path that resolves to just a drive specifier like "C:" or "C:" with trailing separator trimmed away; the check triggers when path.Length==2 and path[1] is a drive/volume separator character.

Common situations: Config value holding just a drive letter (e.g. backup target "D:"); string splitting that cut a path down to the drive; Path.GetPathRoot result passed directly as the directory to create; user input "C:" accepted by a UI.

Related errors


AI-assisted analysis of peass-ng/PEASS-ng@53fb989abc (2026-09-02). Data as JSON: /api/errors/16b122dcdf299c8b. Report an issue: GitHub.