subhra74/xdm · error · IOException

Unable to read state:

Error message

Unable to read state: 

What it means

DownloadStateStore.LoadSingleSourceHTTPDownloaderState throws IOException("Unable to read state: <id>") when the transacted read of <id>.state leaves the state variable null after SingleSourceHTTPDownloaderStateFromBytes runs. This is the DownloadStateStore twin of the DownloadStateIO loader: it enforces that a stored state file for a single-source HTTP download either loads completely or throws.

Solutions

  1. Delete the offending <id>.state from Config.DataDir and restart the download.
  2. Restore the state file from backup, matching the XDM version that wrote it.
  3. Check for orphaned transaction temp files next to the state file and clean/restore as appropriate.
  4. If recurring, verify disk health and free space on the volume holding Config.DataDir.

Example fix

// before
var state = DownloadStateStore.LoadSingleSourceHTTPDownloaderState(id); // throws
// after
SingleSourceHTTPDownloaderState state;
try { state = DownloadStateStore.LoadSingleSourceHTTPDownloaderState(id); }
catch (IOException) { DownloadStateStore.DeleteState(id); state = null; /* start fresh */ }
Defensive patterns

Strategy: try-catch

Validate before calling

var path = Path.Combine(Config.DataDir, id + ".state");
if (!File.Exists(path) || new FileInfo(path).Length == 0)
{
    // start a fresh download instead of calling Load
}

Type guard

static bool StateFileLooksValid(string dataDir, string id)
{
    var p = Path.Combine(dataDir, id + ".state");
    try { return File.Exists(p) && new FileInfo(p).Length > 0; }
    catch (IOException) { return false; }
}

Try / catch

SingleSourceHTTPDownloaderState state;
try { state = DownloadStateStore.LoadSingleSourceHTTPDownloaderState(id); }
catch (IOException)
{
    DownloadStateStore.DeleteState(id);
    state = null; // restart download
}

Prevention

When it happens

Trigger: Calling DownloadStateStore.LoadSingleSourceHTTPDownloaderState(id) with a corrupt, empty, truncated, or format-incompatible <id>.state file in Config.DataDir, causing the byte-level deserializer to return null.

Common situations: Crash or forced termination between state-write and commit; XDM upgrade changing the state binary layout; disk corruption; users manually restoring/pasting state files from other installs.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of subhra74/xdm@1ca5a25aae (2026-09-13). Data as JSON: /api/errors/3c2531e645dcad6a. Report an issue: GitHub.

Appendix: source

Thrown at app/XDM/XDM.Core/IO/DownloadStateStore.cs:72

#if NET35
                ms.CopyTo(stream);
#endif
            });
        }
    }

    public static class DownloadStateStore
    {
        public static SingleSourceHTTPDownloaderState LoadSingleSourceHTTPDownloaderState(string id)
        {
            SingleSourceHTTPDownloaderState? state = null;
            TransactedBinaryDataReader.Read($"{id}.state", Config.DataDir, r =>
            {
                state = SingleSourceHTTPDownloaderStateFromBytes(r);
            });
            if (state == null)
            {
                throw new IOException("Unable to read state: " + id);
            }
            return state;
        }

        private static SingleSourceHTTPDownloaderState SingleSourceHTTPDownloaderStateFromBytes(BinaryReader r)
        {
            var state = new SingleSourceHTTPDownloaderState
            {
                Id = r.ReadString(),
                TempDir = XDM.Messaging.StreamHelper.ReadString(r),
                FileSize = r.ReadInt64(),
                LastModified = DateTime.FromBinary(r.ReadInt64()),
                SpeedLimit = r.ReadInt32(),
                Url = new Uri(r.ReadString())
            };
            if (r.ReadBoolean())
            {
                XDM.Messaging.StreamHelper.ReadStateHeaders(r, out Dictionary<string, List<string>> headers);

View on GitHub (pinned to 1ca5a25aae)