Unity-Technologies/UnityCsReference · error · IOException

FileUtil.OpenRead: Invalid UDS hash in 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.

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.

Appendix: 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)