dotnet/machinelearning · error · IOException

Model file still got locked after 5 seconds, fail to reload.

Error message

Model file {_filePath} still got locked after 5 seconds, fail to reload.

What it means

FileModelLoader.LoadModel opens the model file with a 5-second retry loop via WaitForFile; if the file remains locked by another process after 5 seconds it returns null and this IOException is thrown so the reload aborts instead of loading a partial or unreadable model. The ML.NET context never receives a stream, so _model keeps its previous value.

Solutions

  1. Ensure the producer writes the model atomically: write to a temp file and File.Move/replace onto the watched path so readers never see a locked file
  2. Close the application or process holding an exclusive handle on the model file before triggering reload
  3. Increase tolerance by retrying the load in your own code (catch IOException and call LoadModel again after a delay)
  4. Exclude the model directory from antivirus real-time scanning

Example fix

// before: producer overwrites watched file directly
mlContext.Model.Save(model, schema, File.Create(modelPath));
// after: atomic replace
var tmp = modelPath + ".tmp";
using (var fs = File.Create(tmp)) mlContext.Model.Save(model, schema, fs);
File.Move(tmp, modelPath, overwrite: true);
Defensive patterns

Strategy: retry

Validate before calling

// before triggering reload
var fi = new FileInfo(modelPath);
using (var probe = fi.Open(FileMode.Open, FileAccess.Read, FileShare.Read)) { } // throws IOException while locked

Type guard

bool IsFileReadable(string path) { try { using var _ = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read); return true; } catch (IOException) { return false; } }

Try / catch

try { loader.Start(); } catch (IOException ex) when (ex.Message.Contains("still got locked")) { await Task.Delay(TimeSpan.FromSeconds(5)); retryLoad(); }

Prevention

When it happens

Trigger: Calling Start() or a file watcher change (WatcherChanged) triggering LoadModel() while the .zip model file is held open with an exclusive lock (FileShare incompatible with Read) for over 5 seconds.

Common situations: Another process (e.g. a trainer, backup/AV scanner, or an mlnet CLI training job) is still writing or holding the model file when the app hot-swaps it; copying the model over the same path without atomic rename; antivirus holding the file briefly after write.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


AI-assisted analysis of dotnet/machinelearning@7b76e69cf9 (2026-09-11). Data as JSON: /api/errors/9899fad930919e61. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.Extensions.ML/ModelLoaders/FileModelLoader.cs:136

                catch (IOException)
                {
                    if (fs != null)
                    {
                        fs.Dispose();
                    }
                    Thread.Sleep(50);
                }
            }

            return null;
        }

        //internal virtual for testing purposes.
        internal virtual void LoadModel()
        {
            var fs = WaitForFile(_filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            if (fs == null)
                throw new IOException($"Model file {_filePath} still got locked after 5 seconds, fail to reload.");

            using (fs)
            {
                _model = _context.Model.Load(fs, out _);
            }
        }

        public void Dispose()
        {
            _watcher?.Dispose();
        }

        internal static class EventIds
        {
            public static readonly EventId FileReloadBegin = new EventId(100, "FileReloadBegin");
            public static readonly EventId FileReloadEnd = new EventId(101, "FileReloadEnd");
            public static readonly EventId FileReload = new EventId(102, "FileReload");
            public static readonly EventId FileReloadError = new EventId(103, nameof(FileReloadError));

View on GitHub (pinned to 7b76e69cf9)