felixse/FluentTerminal · error · FormatException

UserInfo part contains {parts.Length} elements.

Error message

UserInfo part contains {parts.Length} elements.

What it means

Thrown by SshConnectViewModel.ParseUri when uri.UserInfo split on ';' yields more than 2 parts. The URI scheme expects at most two semicolon-delimited segments: part[0] = username, part[1] = optional SSH options (e.g. IdentityFile=...). A third segment is treated as a malformed SSH/Mosh URI and raises FormatException.

Source

Thrown at FluentTerminal.App.ViewModels/Profiles/SshConnectViewModel.cs:404

            IApplicationView applicationView, ITrayProcessCommunicationService trayProcessCommunicationService,
            IFileSystemService fileSystemService, IApplicationDataContainer historyContainer)
        {
            var vm = new SshConnectViewModel(settingsService, applicationView, trayProcessCommunicationService,
                fileSystemService)
            {
                Host = uri.Host,
                UseMosh = MoshUriScheme.Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase)
            };

            if (uri.Port >= 0)
                vm.SshPort = (ushort)uri.Port;

            if (!string.IsNullOrEmpty(uri.UserInfo))
            {
                string[] parts = uri.UserInfo.Split(';');

                if (parts.Length > 2)
                    throw new FormatException($"UserInfo part contains {parts.Length} elements.");

                vm.Username = HttpUtility.UrlDecode(parts[0]);

                if (parts.Length > 1)
                {
                    // For now we are only interested in IdentityFile option
                    Tuple<string, string> identityFileOption = ParseParams(parts[1], ',').FirstOrDefault(p =>
                        string.Equals(p.Item1, IdentityFileOptionName, StringComparison.OrdinalIgnoreCase));

                    vm.IdentityFile = identityFileOption?.Item2;
                }
            }

            // ReSharper disable once ConstantConditionalAccessQualifier
            string queryString = uri.Query?.Trim();

            if (string.IsNullOrEmpty(queryString))
            {

View on GitHub (pinned to ba83ec485e)

Solutions

  1. Encode any ';' within username or option values as %3B before constructing the URI, or avoid ';' in values.
  2. Restrict UserInfo to username only, or username plus a single options segment: ssh://user;IdentityFile=path@host.
  3. Validate the URI format in the UI before calling ParseUri and show a helpful error.

Example fix

// before
string[] parts = uri.UserInfo.Split(';');
if (parts.Length > 2)
    throw new FormatException($"UserInfo part contains {parts.Length} elements.");

// after - tolerate extra segments by taking only the first two
string[] parts = uri.UserInfo.Split(';');
if (parts.Length > 2)
    throw new FormatException($"UserInfo has {parts.Length} segments; expected at most user[;options].");
Defensive patterns

Strategy: validation

Validate before calling

// Validate UserInfo shape before ParseUri consumes it.
if (!string.IsNullOrEmpty(uri.UserInfo))
{
    var segs = uri.UserInfo.Split(';');
    if (segs.Length > 2) throw new FormatException($"SSH UserInfo has {segs.Length} segments; expected user[;options].");
}

Type guard

static bool IsValidSshUserInfo(Uri uri) => string.IsNullOrEmpty(uri.UserInfo) || uri.UserInfo.Split(';').Length <= 2;

Try / catch

try { vm = SshConnectViewModel.ParseUri(uri, ...); }
catch (FormatException ex) { notifyUser($"Invalid SSH link: {ex.Message}"); }

Prevention

When it happens

Trigger: ParseUri is given an ssh:// or mosh:// URI whose UserInfo contains three or more ';' separators, e.g. ssh://user;opt1=x;opt2=y@host. The `parts.Length > 2` guard trips before any field is read.

Common situations: User pastes a malformed SSH URL with extra semicolons; an IdentityFile option value itself contains a semicolon (unencoded); a copy-paste from a config generator inserts extra segments; URL-encoding was not applied to special characters in UserInfo.

Related errors


AI-assisted analysis of felixse/FluentTerminal@ba83ec485e (2026-08-13). Data as JSON: /api/errors/2f9075a1e08a2dfb. Report an issue: GitHub.