{"record":{"id":"59465e2bec22d722","repo":"spectreconsole/spectre.console","slug":"a-link-has-already-been-set","errorCode":null,"errorMessage":"A link has already been set.","messagePattern":"A link has already been set\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Spectre.Console.Ansi/AnsiMarkupTagParser.cs","lineNumber":10,"sourceCode":"namespace Spectre.Console;\n\ninternal static class AnsiMarkupTagParser\n{\n    public static (Style Style, Link? Link) Parse(string text)\n    {\n        var result = Parse(text, out var error);\n        if (error != null)\n        {\n            throw new InvalidOperationException(error);\n        }\n\n        return result ?? throw new InvalidOperationException(\"Could not parse style.\");\n    }\n\n    public static bool TryParse(string text, [NotNullWhen(true)] out (Style Style, Link?)? result)\n    {\n        result = Parse(text, out _);\n        return result != null;\n    }\n\n    private static (Style Style, Link? Link)? Parse(string text, out string? error)\n    {\n        var effectiveDecoration = (Decoration?)null;\n        var effectiveForeground = (Color?)null;\n        var effectiveBackground = (Color?)null;\n        var effectiveLink = (string?)null;\n","sourceCodeStart":1,"sourceCodeEnd":28,"githubUrl":"https://github.com/spectreconsole/spectre.console/blob/0acc92fada6c42f13984e79c2b5f3d993bdfb099/src/Spectre.Console.Ansi/AnsiMarkupTagParser.cs#L1-L28","documentation":"Inside the private AnsiMarkupTagParser.Parse, a second `link=...` clause is encountered when effectiveLink is already set. The error string is returned and re-thrown by the public Parse as InvalidOperationException. A bare `link` (auto-link) does not conflict, only explicit `link=` does.","triggerScenarios":"A single tag containing two `link=` clauses, e.g. `[link=http://a.com link=http://b.com]text[/]`, passed to AnsiMarkup.Parse/Write.","commonSituations":"Merging two styled spans and accidentally concatenating their link attributes; templating that appends a default link to a tag that already has one.","solutions":["Use only one `link=` per tag","Split into separate tags if two different links are genuinely needed","For an auto-link (URL derived from text), use bare `link` instead of `link=`"],"exampleFix":"// before\nAnsiMarkup.Parse(\"[link=http://a.com link=http://b.com]click[/]\");\n\n// after\nAnsiMarkup.Parse(\"[link=http://a.com]click[/]\");","handlingStrategy":"validation","validationCode":"// Ensure at most one link= clause per tag:\npublic static bool HasSingleLink(string tag)\n    => tag.Split(' ').Count(p => p.StartsWith(\"link=\", StringComparison.OrdinalIgnoreCase)) <= 1;","typeGuard":null,"tryCatchPattern":"try { var segments = AnsiMarkup.Parse(markup); }\ncatch (InvalidOperationException ex) when (ex.Message == \"A link has already been set.\")\n{ /* rebuild the tag with a single link= */ }","preventionTips":["Define links once per tag; reuse bare `link` for auto-links","When merging style fragments, deduplicate link= attributes","Prefer composing separate tags over cramming multiple links into one"],"tags":["markup","link","parsing","spectre-console"],"backgroundTag":null,"analyzedSha":"0acc92fada6c42f13984e79c2b5f3d993bdfb099","analyzedAt":"2026-08-13T18:27:21.983Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}