NickeManarin/ScreenToGif · error · Exception
It was not possible to get a list of known screens.
Error message
It was not possible to get a list of known screens.
What it means
Thrown by the Recorder's monitor-selection routine when MonitorHelper.AllMonitorsGranular() returns an empty list, so none of the three FirstOrDefault fallbacks (point-containing, primary, any) resolve a monitor. AllMonitorsGranular delegates to the AllMonitors getter which drives User32.EnumDisplayMonitors via a callback closure; if that native enumeration yields zero monitors, the List is empty. The throw means the window cannot determine which screen to anchor itself to.
Source
Thrown at ScreenToGif/Windows/Recorder.xaml.cs:1430
{
UserSettings.All.RecorderLeft = Arguments.Region.Left - Constants.LeftOffset;
UserSettings.All.RecorderTop = Arguments.Region.Top - Constants.TopOffset;
UserSettings.All.RecorderWidth = (int)Arguments.Region.Width + Constants.HorizontalOffset;
UserSettings.All.RecorderHeight = (int)Arguments.Region.Height + Constants.VerticalOffset;
Arguments.Region = Rect.Empty;
}
}
//Since the list of monitors could have been changed, it needs to be queried again.
_viewModel.Monitors = MonitorHelper.AllMonitorsGranular();
//Detect closest screen to the point (previously selected top/left point or current mouse coordinate).
var point = startup ? (double.IsNaN(UserSettings.All.RecorderTop) || double.IsNaN(UserSettings.All.RecorderLeft) ?
CursorHelper.GetMousePosition(_scale, Left, Top) : new Point((int)UserSettings.All.RecorderLeft, (int)UserSettings.All.RecorderTop)) : new Point((int) Left, (int) Top);
var closest = _viewModel.Monitors.FirstOrDefault(x => x.Bounds.Contains(point)) ?? _viewModel.Monitors.FirstOrDefault(x => x.IsPrimary) ?? _viewModel.Monitors.FirstOrDefault();
if (closest == null)
throw new Exception("It was not possible to get a list of known screens.");
//Move the window to the correct location.
var left = UserSettings.All.RecorderLeft;
var top = UserSettings.All.RecorderTop;
if (double.IsNaN(UserSettings.All.RecorderTop) || double.IsNaN(UserSettings.All.RecorderLeft))
{
left = closest.WorkingArea.Left + closest.WorkingArea.Width / 2d - ActualWidth / 2d;
top = closest.WorkingArea.Top + closest.WorkingArea.Height / 2d - ActualHeight / 2d;
}
else
{
//To much to the Left.
if (closest.WorkingArea.Left > UserSettings.All.RecorderLeft + UserSettings.All.RecorderWidth - 100)
left = closest.WorkingArea.Left;
//Too much to the top.
if (closest.WorkingArea.Top > UserSettings.All.RecorderTop + UserSettings.All.RecorderHeight - 100)View on GitHub (pinned to a4d0a67c21)
Solutions
- Ensure at least one display is active and powered on before opening the recorder.
- Reconnect the disconnected monitor, then close and reopen the recorder window so AllMonitorsGranular re-enumerates.
- Delay the reposition call until the SystemEvents.DisplaySettingsChanged event has fully fired and the desktop is stable.
- Do not launch the recorder from a non-interactive session (service/scheduled task) — it needs an interactive desktop to enumerate monitors.
- Add a guard: if the list is empty, fall back to SystemParameters.PrimaryScreenWidth/Height instead of throwing, or retry enumeration after a short delay.
Example fix
// before
_viewModel.Monitors = MonitorHelper.AllMonitorsGranular();
var point = /* ... */;
var closest = _viewModel.Monitors.FirstOrDefault(x => x.Bounds.Contains(point)) ?? _viewModel.Monitors.FirstOrDefault(x => x.IsPrimary) ?? _viewModel.Monitors.FirstOrDefault();
if (closest == null)
throw new Exception("It was not possible to get a list of known screens.");
// after: retry + graceful fallback to SystemParameters primary screen
_viewModel.Monitors = MonitorHelper.AllMonitorsGranular();
for (var i = 0; _viewModel.Monitors.Count == 0 && i < 3; i++)
_viewModel.Monitors = MonitorHelper.AllMonitorsGranular();
var point = /* ... */;
var closest = _viewModel.Monitors.FirstOrDefault(x => x.Bounds.Contains(point))
?? _viewModel.Monitors.FirstOrDefault(x => x.IsPrimary)
?? _viewModel.Monitors.FirstOrDefault();
if (closest == null)
{
// No enumerated monitor — anchor to the WPF primary-screen rect instead of crashing.
closest = new Monitor { Bounds = new Rect(0, 0, SystemParameters.PrimaryScreenWidth, SystemParameters.PrimaryScreenHeight),
WorkingArea = SystemParameters.WorkArea, IsPrimary = true };
LogWriter.Log(new InvalidOperationException("Monitor enumeration returned empty list; falling back to primary screen."), "Monitor enumeration fallback.");
} Defensive patterns
Strategy: validation
Validate before calling
// Validate monitor enumeration before using it for positioning.
var monitors = MonitorHelper.AllMonitorsGranular();
if (monitors == null || monitors.Count == 0)
{
// Retry once after the display subsystem settles.
await Task.Delay(200);
monitors = MonitorHelper.AllMonitorsGranular();
}
if (monitors.Count == 0)
throw new InvalidOperationException("No displays available; cannot position the recorder.");
_viewModel.Monitors = monitors; Type guard
// Ensure a non-empty monitor list before resolving 'closest'.
static bool HasUsableMonitor(List<Monitor> monitors, Point point) =>
monitors.Count > 0 &&
(monitors.Any(x => x.Bounds.Contains(point)) || monitors.Any(x => x.IsPrimary));
if (!HasUsableMonitor(_viewModel.Monitors, point))
return; // skip repositioning, keep current location Try / catch
try
{
// ... monitor selection + positioning ...
}
catch (Exception e) when (e.Message.Contains("list of known screens"))
{
LogWriter.Log(e, "Monitor enumeration failed during recorder positioning.");
// Keep the window at its last known position instead of crashing.
} Prevention
- Subscribe to SystemEvents.DisplaySettingsChanged and defer repositioning until the new list is stable.
- Never assume AllMonitorsGranular() returns non-empty — always null/empty-check before FirstOrDefault chains.
- Avoid launching the recorder from a non-interactive session; it needs a live desktop.
- Cache the last-good monitor rect so a transient enumeration gap doesn't break positioning.
When it happens
Trigger: Called during recorder startup/positioning (startup=true) or repositioning. AllMonitorsGranular() returns an empty list because User32.EnumDisplayMonitors invoked no callback items — typically when the calling thread has no visible desktop, the session is in transition (logoff/lock/UAC secure desktop), or all displays were disconnected while the window was open.
Common situations: All monitors disconnected / powered off while ScreenToGif was open; running on a session that lost its desktop (fast-user-switch, RDP disconnect); the window is being positioned during a WM_DISPLAYCHANGE before the new monitor list is populated; headless service context with no interactive desktop; display driver crashed and the GDI desktop is momentarily gone.
Related errors
- It was not possible to get a list of known screens.
- It was not possible to get a list of known screens.
- It was not possible to move the current selected region to t
- Only 24 and 32 bpp images are supported.
- Could not find a proper output device for the area of L: {Le
AI-assisted analysis of NickeManarin/ScreenToGif@a4d0a67c21 (2026-08-13).
Data as JSON: /api/errors/d4eb33f148cdc270.
Report an issue: GitHub.