cefsharp/CefSharp · error · Exception
Frame is invalid, unable to continue.
Error message
Frame is invalid, unable to continue.
What it means
Thrown by the DownloadUrl extension method when frame.IsValid is false. A frame becomes invalid after navigation, frame detach, or browser disposal — CEF has already torn down the underlying CefFrame handle. The method cannot create a request on a dead frame, so it refuses immediately rather than silently failing on the CEF UI thread.
Source
Thrown at CefSharp.Core/WebBrowserExtensionsEx.cs:65
tcs.TrySetResult(entry);
});
return tcs.Task;
}
/// <summary>
/// Downloads the specified <paramref name="url"/> and calls <paramref name="completeHandler"/>
/// when the download is complete. Makes a GET Request.
/// </summary>
/// <param name="frame">valid frame</param>
/// <param name="url">url to download</param>
/// <param name="completeHandler">Action to be executed when the download is complete.</param>
public static void DownloadUrl(this IFrame frame, string url, Action<IUrlRequest, Stream> completeHandler)
{
if (!frame.IsValid)
{
throw new Exception("Frame is invalid, unable to continue.");
}
//Can be created on any valid CEF Thread, here we'll use the CEF UI Thread
Cef.UIThreadTaskFactory.StartNew(delegate
{
var request = frame.CreateRequest(false);
request.Method = "GET";
request.Url = url;
var memoryStream = new MemoryStream();
var urlRequestClient = Fluent.UrlRequestClient
.Create()
.OnDownloadData((req, stream) =>
{
stream.CopyTo(memoryStream);
})View on GitHub (pinned to 16bc6e0711)
Solutions
- Check frame.IsValid immediately before calling DownloadUrl and skip if false.
- Reacquire the frame from browser.MainFrame at the call site rather than caching it long-term.
- Move the download trigger into a lifecycle-safe handler (e.g. LoadingStateChanged with the current frame captured at call time).
Example fix
// before
frame.DownloadUrl(url, OnComplete);
// after
if (frame.IsValid)
{
frame.DownloadUrl(url, OnComplete);
} Defensive patterns
Strategy: validation
Validate before calling
if (frame == null || !frame.IsValid) return; frame.DownloadUrl(url, handler);
Type guard
public static bool IsFrameUsable(IFrame f) => f != null && f.IsValid;
Try / catch
try { frame.DownloadUrl(url, handler); }
catch (Exception ex) when (ex.Message.Contains("Frame is invalid")) { /* re-fetch frame or skip */ } Prevention
- Never cache IFrame references across navigations.
- Check IsValid immediately before frame-dependent calls.
- Capture the frame at call-time from browser.MainFrame.
When it happens
Trigger: Calling frame.DownloadUrl(url, handler) after the page navigated away, after the frame was removed from the DOM, or after the browser was disposed. Common in FrameLoadStart/FrameLoadEnd racing or in async callbacks that outlive the frame.
Common situations: Storing an IFrame reference in a field and using it later in an async continuation. Handling a download triggered from a popup frame that closed. Cross-frame access after a redirect changed main frame identity.
Related errors
- IBrowser
- Unable to invoke ExecuteDevToolsMethod on CEF UI Thread.
- urlRequestClient
- frame
- An instance of the underlying offscreen browser has already
AI-assisted analysis of cefsharp/CefSharp@16bc6e0711 (2026-08-13).
Data as JSON: /api/errors/817210aa9ce52672.
Report an issue: GitHub.