tui-cs/Terminal.Gui · error · ArgumentException
The source stream must be seekable (CanSeek property)
Error message
The source stream must be seekable (CanSeek property)
What it means
Thrown by the HexView.Source setter when the supplied Stream has CanSeek == false. HexView must seek arbitrarily through the byte source to render any address, apply edits, and navigate, so a non-seekable stream (e.g. a network pipe or unbuffered console input) cannot back the view. The check is a hard precondition in the setter, before any state is mutated.
Source
Thrown at Terminal.Gui/Views/HexView.cs:320
public void DiscardEdits () => _edits = new SortedDictionary<long, byte> ();
private Stream? _source;
/// <summary>
/// Sets or gets the <see cref="Stream"/> the <see cref="HexView"/> is operating on; the stream must support
/// seeking ( <see cref="Stream.CanSeek"/> == true).
/// </summary>
/// <value>The source.</value>
public Stream? Source
{
get => _source;
set
{
ArgumentNullException.ThrowIfNull (value);
if (!value.CanSeek)
{
throw new ArgumentException (@"The source stream must be seekable (CanSeek property)");
}
DiscardEdits ();
_source = value;
SetBytesPerLine ();
if (Address > _source.Length)
{
Address = 0;
}
SetNeedsLayout ();
SetNeedsDraw ();
}
}
/// <summary>The bytes length per line.</summary>
public int BytesPerLineView on GitHub (pinned to 2e47b11478)
Solutions
- Buffer the source into a MemoryStream first: var ms = new MemoryStream(); source.CopyTo(ms); ms.Position = 0; hexView.Source = ms;
- If the data is file-backed, open with File.OpenRead which is always seekable.
- Subclass the stream and override CanSeek => true only if you genuinely implement Position/Seek/Length.
- Pre-validate stream.CanSeek before assigning to Source and surface a user-facing message instead of letting the library throw.
Example fix
// before using var netStream = httpClient.GetStreamAsync(url).Result; hexView.Source = netStream; // throws 160 // after using var netStream = httpClient.GetStreamAsync(url).Result; using var ms = new MemoryStream(); netStream.CopyTo(ms); ms.Position = 0; hexView.Source = ms;
Defensive patterns
Strategy: validation
Validate before calling
if (stream is null || !stream.CanSeek)
{
// buffer or reject before assigning
using var ms = new MemoryStream();
stream?.CopyTo(ms);
ms.Position = 0;
hexView.Source = ms;
return;
}
hexView.Source = stream; Type guard
static bool IsUsableForHexView(Stream? s) => s is { CanSeek: true }; Prevention
- Always buffer network/pipe streams into a MemoryStream before assigning to HexView.Source.
- Prefer File.OpenRead for file sources — it is always seekable.
- In test fakes, override CanSeek to return true only when you implement Seek/Position/Length.
When it happens
Trigger: Assigning HexView.Source to a Stream whose CanSeek is false, such as a NetworkStream, an unbuffered Console.OpenStandardInput(), a PipeReader-as-stream, or a DeflateStream/GZipStream read stream. Also happens when wrapping a stream that loses seekability after construction.
Common situations: Loading bytes directly from a socket or HTTP response without buffering first; using a forward-only crypto/decoder stream; unit tests feeding a fake stream that forgets to override CanSeek to true.
Related errors
- Zoom level must be a finite number.
- Maximum sixel palette colors must be greater than zero.
- value
- value
- SelectedItem must be greater than 0 or less than the number
AI-assisted analysis of tui-cs/Terminal.Gui@2e47b11478 (2026-08-13).
Data as JSON: /api/errors/f6000bba195d1a52.
Report an issue: GitHub.