dotnet/wpf · error · ArgumentException
SR.SeekNegative
Error message
SR.SeekNegative
What it means
ArgumentException (SR.SeekNegative) thrown by VersionedStreamOwner.Seek when the computed new position (depending on SeekOrigin.Begin/Current/End plus the offset) is negative — i.e. seeking before the start of the stream data. .NET streams do not allow negative positions, so the call is rejected.
Solutions
- Clamp or validate the computed target position to >= 0 before calling Seek
- Capture positions with a positive-origin Seek (SeekOrigin.Begin) rather than relative arithmetic
- Restore saved positions only on the same stream they were captured from
- Use checked arithmetic for offset computations to surface underflow at the right place
Example fix
// before: unguarded relative seek from End long target = fileLength + delta; // delta may underflow stream.Seek(target, SeekOrigin.Begin); // after: clamp to the valid range long target = Math.Max(0, fileLength + delta); stream.Seek(target, SeekOrigin.Begin);
Defensive patterns
Strategy: validation
Validate before calling
static long ClampSeek(long origin, long offset, long length) => Math.Max(0, origin switch
{
SeekOrigin.Begin => offset,
SeekOrigin.Current => offset,
SeekOrigin.End => length + offset,
_ => throw new ArgumentOutOfRangeException(nameof(origin))
}); Try / catch
try
{
stream.Seek(target, SeekOrigin.Begin);
}
catch (ArgumentException ex) when (ex.Message.Contains("negative"))
{
logger.LogWarning(ex, "Seek before start of stream; clamping to 0.");
stream.Seek(0, SeekOrigin.Begin);
} Prevention
- Always compute seek targets with checked, positive-anchored arithmetic
- Clamp computed positions to [0, Length] before seeking
- Never restore saved positions onto a different stream instance
- Unit-test seek math with offsets larger than stream length
When it happens
Trigger: Calling Seek with a negative offset from SeekOrigin.Begin, or an offset from Current/End large enough that Length+offset < 0 (e.g. Seek(-1000, SeekOrigin.End) on a 100-byte stream). Reached both directly and via the Position setter.
Common situations: Off-by-sign errors when computing relative offsets; saving/restoring a position captured from a different stream; integer underflow when mixing Int32 offsets with long lengths; seeking relative to End on streams assumed larger than they are.
Related errors
- SR.SeekOriginInvalid
- ArgumentOutOfRangeException(nameof(offset))
- can’t seek on baseStream
- SeekOrigin value is not valid.
- SeekOrigin value is not valid.
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/3618ba68db6dec6f.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/CompoundFile/VersionedStreamOwner.cs:85
long temp = -1;
switch (origin)
{
// seek beyond the FormatVersion
case SeekOrigin.Begin:
temp = offset;
break;
case SeekOrigin.Current:
checked { temp = Position + offset; }
break;
case SeekOrigin.End:
checked { temp = Length + offset; }
break;
}
if (temp < 0)
throw new ArgumentException(SR.SeekNegative);
checked { BaseStream.Position = temp + _dataOffset; }
return temp;
}
/// <summary>
/// SetLength
/// </summary>
public override void SetLength(long newLength)
{
ArgumentOutOfRangeException.ThrowIfNegative(newLength);
WriteAttempt();
checked { BaseStream.SetLength(newLength + _dataOffset); }
}
/// <summary>
/// FlushView on GitHub (pinned to 81131a70a4)