dotnet/wpf · error · ArgumentException
SR.Cursor_InvalidStream
Error message
SR.Cursor_InvalidStream
What it means
LegacyLoadFromStream writes the stream to a temp file and loads it via LoadImage; if the resulting _cursorHandle is null or invalid, it throws ArgumentException(SR.Cursor_InvalidStream). This is the compat (quirk-flagged) stream-loading path, and the error means the stream's bytes could not be turned into a valid native cursor handle.
Solutions
- Seek the stream to position 0 (stream.Seek(0, SeekOrigin.Begin)) before constructing the Cursor.
- Verify the stream actually contains .cur/.ani bytes (check length and first bytes) rather than another resource.
- Confirm the embedded resource name and that it was copied into the assembly.
- Catch ArgumentException around Cursor construction and fall back to a built-in cursor.
Example fix
// before
using var s = assembly.GetManifestResourceStream("App.cursor.cur");
cursor = new Cursor(s);
// after
using var s = assembly.GetManifestResourceStream("App.Resources.cursor.cur");
s.Seek(0, SeekOrigin.Begin);
cursor = new Cursor(s); Defensive patterns
Strategy: validation
Validate before calling
using var s = assembly.GetManifestResourceStream(resourcePath);
if (s == null || s.Length == 0) throw new InvalidOperationException($"Resource missing or empty: {resourcePath}");
s.Seek(0, SeekOrigin.Begin);
Cursor cursor = new Cursor(s); Type guard
bool IsValidCursorStream(Stream s) => s != null && s.CanSeek && s.Length > 0 && s.Position == 0;
Try / catch
try { cursor = new Cursor(stream); }
catch (ArgumentException ex)
{ logger.LogWarning("Stream is not a valid cursor: {Msg}", ex.Message); cursor = Cursors.Default; } Prevention
- Always Seek(0) a stream before handing it to new Cursor(Stream).
- Verify embedded resource names with assembly.GetManifestResourceNames().
- Check stream length > 0 before construction.
- Keep a built-in cursor as fallback for resource-loading failures.
When it happens
Trigger: new Cursor(Stream) (via LoadFromStream → LegacyLoadFromStream, quirk flag enabled) with a stream whose content is not a valid .cur/.ani image or is empty.
Common situations: Embedding a .cur as an assembly resource and passing the wrong manifest resource stream (getting a different/empty resource); passing a stream positioned after the data (need Seek(0)); passing non-cursor image data.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- ArgumentOutOfRangeException(nameof(offset))
- can’t seek on baseStream
- Image_CantDealWithStream
- Image_NoDecodeFrames (stream)
- Image_OriginalStreamReadOnly
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/970ead7779de76b7.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Cursor.cs:249
}
// Write any remaining bytes
fileStream.Write(cursorData, offset: 0, count: dataSize);
}
}
// This method is called with File Write permission still asserted.
// However, this method just reads this file into an icon.
_cursorHandle = UnsafeNativeMethods.LoadImageCursor(IntPtr.Zero,
filePath,
NativeMethods.IMAGE_CURSOR,
0, 0,
NativeMethods.LR_DEFAULTCOLOR |
NativeMethods.LR_LOADFROMFILE |
(_scaleWithDpi? NativeMethods.LR_DEFAULTSIZE : 0x0000));
if (_cursorHandle == null || _cursorHandle.IsInvalid)
{
throw new ArgumentException(SR.Cursor_InvalidStream);
}
}
finally
{
try
{
File.Delete(filePath);
}
catch(System.IO.IOException)
{
// We may not be able to delete the file if it's being used by some other process (e.g. Anti-virus check).
// There's nothing we can do in that case, so just eat the exception and leave the file behind
}
}
}
//**** end of DEAD CODE ****//
private void LoadFromStream(Stream cursorStream)View on GitHub (pinned to 81131a70a4)