Unity-Technologies/UnityCsReference · error · IOException

FileUtil.OpenRead: Invalid UDS hash in path '{path}'

Error message

FileUtil.OpenRead: Invalid UDS hash in path '{path}'

What it means

OpenReadUDS extracts the trailing path segment as a Hash128 string and parses it; if Hash128.Parse yields an invalid hash, the path was not a well-formed UDS (Unity Data Storage) content path and the method throws IOException. This guards the native UDS.Acquire call from receiving garbage.

Source

Thrown at Editor/Mono/FileUtil.cs:51

                // materialise the data through the native VFS read
                byte[] data = ReadAllBytesInternal(path);
                return new MemoryStream(data, writable: false);
            }

            // The 'physical' path for a VirtualArtifact will be a UDS virtual path
            if (physicalPath.StartsWith(k_UdsPathPrefix, StringComparison.Ordinal))
                return OpenReadUDS(physicalPath);

            // Fall back to opening the physical file in the normal way
            return File.Open(physicalPath, FileMode.Open, FileAccess.Read, FileShare.Read);
        }

        static Stream OpenReadUDS(string path)
        {
            string hashStr = path[(path.LastIndexOf('/') + 1)..];
            var hash = Hash128.Parse(hashStr);
            if (!hash.isValid)
                throw new IOException($"FileUtil.OpenRead: Invalid UDS hash in path '{path}'");

            IntPtr handle = UDS.Acquire(hash);
            if (handle == IntPtr.Zero)
                throw new IOException($"FileUtil.OpenRead: Failed to acquire UDS content for '{path}'");

            return new UDSReadStream(handle);
        }

        public static byte[] ReadAllBytes(string path)
        {
            if (string.IsNullOrEmpty(path))
                throw new ArgumentException("Path cannot be null or empty.", nameof(path));

            return ReadAllBytesInternal(path);
        }

        public static string ReadAllText(string path)
        {

View on GitHub (pinned to 225b0fbdb5)

Solutions

  1. Validate the trailing segment with Hash128.Parse before calling OpenRead, or assert the path shape (uds:/<32-hex>).
  2. Do not hand-construct UDS paths; obtain them from the API that owns the virtual artefact.
  3. If paths come from persistence, validate length/format on load and discard malformed entries.

Example fix

// before
using Stream s = FileUtil.OpenRead(udsPath);
// after
string hashStr = udsPath[(udsPath.LastIndexOf('/') + 1)..];
if (!Hash128.Parse(hashStr).isValid) throw new ArgumentException("malformed UDS path");
using Stream s = FileUtil.OpenRead(udsPath);
Defensive patterns

Strategy: validation

Validate before calling

string hashStr = path[(path.LastIndexOf('/') + 1)..];
if (!Hash128.Parse(hashStr).isValid)
    throw new ArgumentException("malformed UDS path", nameof(path));
using Stream s = FileUtil.OpenRead(path);

Type guard

static bool IsWellFormedUdsPath(string p) =>
    p != null && p.StartsWith("uds:/") && Hash128.Parse(p[(p.LastIndexOf('/') + 1)..]).isValid;

Prevention

When it happens

Trigger: A path with the uds:/ prefix whose final segment is not a 32-character hex Hash128 — e.g. truncated, corrupted, manually edited, or a path that looks like UDS but is actually a different virtual scheme.

Common situations: Serialised UDS paths that were truncated by length limits. Manually constructed virtual paths. Logging/transport layers that mangle the path. A version change in the UDS path format.

Related errors


AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13). Data as JSON: /api/errors/e25a76c2fb97807c. Report an issue: GitHub.