tui-cs/Terminal.Gui · error · ArgumentException

The first item must be the original.

Error message

The first item must be the original.

What it means

Thrown by HistoryText.Add when the items collection is empty and the incoming lineStatus is not Original. HistoryText models an undo stack whose first entry must be the baseline 'Original' content; any later edit (Added/Removed/Replaced/etc.) is only valid on top of an existing baseline. Enforcing this keeps the undo/redo invariant that there is always something to revert to.

Source

Thrown at Terminal.Gui/Views/TextInput/HistoryText.cs:29

    public void Add (List<List<Cell>> lines, Point curPos, TextEditingLineStatus lineStatus = TextEditingLineStatus.Original)
    {
        if (lineStatus == TextEditingLineStatus.Original
            && _historyTextItems.Count > 0
            && _historyTextItems.Last ().LineStatus == TextEditingLineStatus.Original)
        {
            return;
        }

        if (lineStatus == TextEditingLineStatus.Replaced
            && _historyTextItems.Count > 0
            && _historyTextItems.Last ().LineStatus == TextEditingLineStatus.Replaced)
        {
            return;
        }

        if (_historyTextItems.Count == 0 && lineStatus != TextEditingLineStatus.Original)
        {
            throw new ArgumentException ("The first item must be the original.");
        }

        if (_idxHistoryText >= 0 && _idxHistoryText + 1 < _historyTextItems.Count)
        {
            _historyTextItems.RemoveRange (_idxHistoryText + 1, _historyTextItems.Count - _idxHistoryText - 1);
        }

        _historyTextItems.Add (new HistoryTextItemEventArgs (lines, curPos, lineStatus));
        _idxHistoryText++;
    }

    public event EventHandler<HistoryTextItemEventArgs?>? ChangeText;

    public void Clear (List<List<Cell>> cellsList)
    {
        _historyTextItems.Clear ();
        _idxHistoryText = -1;
        _originalCellsList.Clear ();

View on GitHub (pinned to 2e47b11478)

Solutions

  1. Always seed history with the original content first: history.Add(originalLines, cursorPos, TextEditingLineStatus.Original);
  2. After clearing history, immediately re-add the current text as Original before recording further edits.
  3. When replaying/snapshotting, ensure the first element carried over is marked Original.

Example fix

// before
history.Add(editedLines, pos, TextEditingLineStatus.Added); // empty history -> throws 174

// after
history.Add(currentLines, pos, TextEditingLineStatus.Original);
history.Add(editedLines, pos, TextEditingLineStatus.Added);
Defensive patterns

Strategy: validation

Validate before calling

if (history is not seeded)
{
    history.Add(currentLines, pos, TextEditingLineStatus.Original);
}
history.Add(editedLines, pos, status);

Type guard

static bool HistoryHasBaseline(HistoryText h) => /* expose whether first item is Original */ true;

Prevention

When it happens

Trigger: Calling HistoryText.Add with a non-Original status before ever adding an Original entry — e.g. recording an edit before initialising history with the document's original lines, or after history was cleared and an edit arrives first.

Common situations: TextView/Editor integration that begins tracking edits before seeding the original text; clearing _historyTextItems then receiving an edit before re-seeding; a copy/replay of history items that omits the leading Original.

Related errors


AI-assisted analysis of tui-cs/Terminal.Gui@2e47b11478 (2026-08-13). Data as JSON: /api/errors/736f39f352ee9908. Report an issue: GitHub.