spectreconsole/spectre.console · error · InvalidOperationException

Encountered malformed markup tag at position {pos}.

Error message

Encountered malformed markup tag at position {pos}.

What it means

ThrowMalformed is the catch-all for malformed opening tags in MarkupTokenizer.ReadMarkup: it fires on EOF reached before the tag closes, an unexpected character after `[/` (the closer must be `[/]`), an unescaped `[` inside a tag body, or input that opens `[` but never supplies a valid `]` terminator. The reported position points at the offending location.

Source

Thrown at src/Spectre.Console.Ansi/AnsiMarkup.cs:434

            {
                currentStylePartCanContainMarkup =
                    (builder.Length == LinkPrefix.Length || builder[^(LinkPrefix.Length + 1)] == ' ')
                    && builder.ToString(builder.Length - LinkPrefix.Length, LinkPrefix.Length)
                        .Equals(LinkPrefix, StringComparison.OrdinalIgnoreCase);
            }
        }

        if (_reader.Eof)
        {
            ThrowMalformed(_reader.Position);
        }

        return new MarkupToken(MarkupTokenKind.Open, builder.ToString(), position);
    }

    [DoesNotReturn]
    private static void ThrowMalformed(int pos) =>
        throw new InvalidOperationException($"Encountered malformed markup tag at position {pos}.");
}

View on GitHub (pinned to 0acc92fada)

Solutions

  1. Ensure every tag is fully formed: `[...]` with a single well-formed body and a closing `]`
  2. Use `[/]` exactly for closers (no other content between the brackets)
  3. Escape any literal `[` or `]` that should appear as text inside a tag context
  4. Validate or try/catch around AnsiMarkup.Parse for dynamic markup

Example fix

// before
AnsiMarkup.Parse("[redtext"); // missing closing bracket

// after
AnsiMarkup.Parse("[red]text[/]");
Defensive patterns

Strategy: try-catch

Validate before calling

// Lightweight sanity check that tags are closed:
public static bool TagsLookWellFormed(string markup)
    => !Regex.IsMatch(markup, @"\[[^\]]*$") && !Regex.IsMatch(markup, @"\[/[^\]]");

Try / catch

try { var segments = AnsiMarkup.Parse(markup); }
catch (InvalidOperationException ex) when (ex.Message.Contains("malformed markup tag"))
{ /* log position from message, fall back to plain text */ }

Prevention

When it happens

Trigger: Inputs such as `"[red"` (no closing bracket), `"[/x"` (bad closer), `"[a[b]"` (unescaped `[` inside tag), or `"[link="` truncated at EOF.

Common situations: Hand-written markup with a typo; dynamically built tags with a missing `]`; truncated strings from a buffer; copy-paste that lost the closing bracket.

Understand the failure class

Related errors


AI-assisted analysis of spectreconsole/spectre.console@0acc92fada (2026-08-13). Data as JSON: /api/errors/0280a049db56c827. Report an issue: GitHub.