dotnet/wpf · error · ArgumentOutOfRangeException
Stream length cannot be negative.
Error message
Stream length cannot be negative.
What it means
RightsManagementEncryptedStream.SetLength validates that the requested new length is non-negative before updating the cached length. A negative length has no meaning for a stream, so the API throws ArgumentOutOfRangeException with SR.CannotMakeStreamLengthNegative. Write() and other size-affecting operations funnel through this method.
Solutions
- Validate newLength >= 0 before calling SetLength and correct or reject the caller-supplied value.
- Clamp with long safeLength = Math.Max(0, newLength); before invoking SetLength.
- If the length originates from parsed metadata, validate it at parse time (e.g. use checked arithmetic / reject negatives) instead of propagating it to the stream.
- If the intent was truncation of only a portion, recompute the delta between current and target lengths explicitly.
- Catch ArgumentOutOfRangeException around SetLength when lengths come from external data and recover by re-opening the stream.
Example fix
// before
stream.SetLength(requestedLength); // requestedLength may be < 0
// after
if (requestedLength < 0)
throw new ArgumentException("computed length must be >= 0", nameof(requestedLength));
stream.SetLength(Math.Max(0, requestedLength)); Defensive patterns
Strategy: validation
Validate before calling
if (newLength < 0)
throw new ArgumentException("newLength must be >= 0", nameof(newLength));
stream.SetLength(newLength); Type guard
bool IsValidSetLength(long newLength) => newLength >= 0 && newLength <= long.MaxValue;
Try / catch
try { stream.SetLength(newLength); }
catch (ArgumentOutOfRangeException) { newLength = Math.Max(0, newLength); stream.SetLength(newLength); } Prevention
- Validate lengths at parse time with checked arithmetic before they reach SetLength.
- Use unsigned/validated intermediates when computing truncation sizes.
- Clamp with Math.Max(0, len) for programmatic resizing.
- Never pass through lengths derived from corrupted file metadata without a sanity check.
When it happens
Trigger: Calling SetLength(negativeValue) directly; a Write() call whose computed end position resolves to a negative length due to a bad buffer/position calculation; passing untrusted parsed lengths through to SetLength.
Common situations: Applying lengths parsed from a corrupted package file; off-by-one or sign errors when computing truncation sizes; wrapping this stream in code that derives newLength from signed arithmetic that underflows.
Related errors
- Cannot set seek pointer to a negative position.
- SeekOrigin value is not valid.
- Stream does not support SetLength.
- A read or write operation references a location outside the…
- Argument out of range (end not contained in view)
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/be4fe33e210f291e.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/CompoundFile/RightsManagementEncryptedStream.cs:165
if (temp < 0)
{
throw new ArgumentOutOfRangeException(nameof(offset), SR.SeekNegative);
}
_streamPosition = temp;
return _streamPosition;
}
/// <summary>
/// See .NET Framework SDK under System.IO.Stream
/// </summary>
public override void SetLength(long newLength)
{
CheckDisposed();
if (newLength < 0)
{
throw new ArgumentOutOfRangeException(nameof(newLength), SR.CannotMakeStreamLengthNegative);
}
_streamCachedLength = newLength;
// We are not caching this transaction for the following reason. The extra data that might
// be added to stream when the new length is higher than the existing length,
// although undefined (could be junk) must be consistent. Consistent
// is defined in a sense of multiple read requests performed on the same stream area.
// In order to guarantee this consistency we either have to come up with some initial value
// (0 or anything else) remember the initialized area (or multiple areas like that if get a set
// of non contiguous writes), and take it into account during all the transactions.
// Alternatively we can get some real bits allocated on the baseStream and take advantage
// of the underlying stream capability to preserve consistent content of the extra bits being
// allocated here.
FlushLength();
if (_streamPosition > Length)
{View on GitHub (pinned to 81131a70a4)