QL-Win/QuickLook · error · ArgumentException

Offset is before the current position in the stream.

Error message

Offset is before the current position in the stream.

What it means

Thrown by the Stream.GetBytes extension used by the PE parser: it computes bytesToSkip = index - stream.Position and requires this to be >= 0. A negative value means the requested `index` is behind the stream's current cursor, and because the method only supports forward skipping (it reads-and-discards), it throws ArgumentException rather than seeking.

Source

Thrown at QuickLook.Plugin/QuickLook.Plugin.PEViewer/PEImageParser/ImageSection.cs:84

    /// </returns>
    public static byte[] GetBytes(this byte[] array, int index, int count)
    {
        byte[] result = new byte[count];
        Buffer.BlockCopy(array, index, result, 0, count);
        return result;
    }

    public static byte[] GetBytes(this Stream stream, long index, int count)
    {
        byte[] buffer = new byte[count];

        // Ensure the stream is at the correct position
        long currentPosition = stream.Position;
        long bytesToSkip = index - currentPosition;

        if (bytesToSkip < 0)
        {
            throw new ArgumentException("Offset is before the current position in the stream.");
        }

        // Skip bytes until reaching the target offset
        while (bytesToSkip > 0)
        {
            int bytesSkipped = (int)Math.Min(bytesToSkip, int.MaxValue);
            stream.Read(new byte[bytesSkipped], 0, bytesSkipped);
            bytesToSkip -= bytesSkipped;
        }

        // Read the required number of bytes
        int bytesRead = stream.Read(buffer, 0, count);
        if (bytesRead < count)
        {
            throw new EndOfStreamException("The stream has fewer bytes available than requested.");
        }

        return buffer;

View on GitHub (pinned to cb5d9c429c)

Solutions

  1. If the stream is seekable, set stream.Position = index before calling GetBytes instead of relying on the skip logic.
  2. Read PE structures in file-offset order so the cursor only moves forward.
  3. Buffer the whole image into a MemoryStream/byte[] and index randomly rather than streaming.
  4. Catch ArgumentException and re-open the stream from the start for out-of-order access.

Example fix

// before
long bytesToSkip = index - currentPosition;
if (bytesToSkip < 0)
    throw new ArgumentException("Offset is before the current position in the stream.");

// after — rewind when seekable
if (index < stream.Position)
{
    if (stream.CanSeek) stream.Position = index;
    else throw new ArgumentException("Offset is before the current position and stream is not seekable.");
}
Defensive patterns

Strategy: validation

Validate before calling

if (index < stream.Position) {
    if (stream.CanSeek) stream.Position = index;
    else throw new ArgumentException("Cannot read backwards on a forward-only stream.");
}

Type guard

static bool CanReadAt(Stream s, long index) => index >= s.Position || s.CanSeek;

Try / catch

try { bytes = stream.GetBytes(index, count); }
catch (ArgumentException) { stream.Position = index; bytes = stream.GetBytes(index, count); }

Prevention

When it happens

Trigger: Calling GetBytes(stream, index, count) with an `index` smaller than stream.Position — e.g. requesting a section whose PointerToRawData is before where the cursor already advanced during header parsing, on a non-seekable or forward-only consumption.

Common situations: Parsing PE structures out of order (reading a later section then an earlier one) without rewinding; using a forward-only stream (network/decompressed) where Position only increases; an off-by-one or wrong offset computed for PointerToRawData.

Related errors


AI-assisted analysis of QL-Win/QuickLook@cb5d9c429c (2026-08-13). Data as JSON: /api/errors/5ceb4de16112427f. Report an issue: GitHub.