6.3 change - When matckingmaking fails: Invalid listen endpoint: 127.0.0.1:7777:7777

I’ve been developing with NGO for 2 years. I was on 6.2 since it came out, no issues. Recently I changed to 6.3. Now I get this when starting a game using the lobby system, where I specify a timeout if no game is found.

This seems like a breaking change somewhere, I’ve never seen this issue before.
My code has always been simple..

  public async Task<ISession> JoinOrCreateMatchmakeSessionWithDirect(
    SessionOptions options
  )
  { 
    await UnityServices.InitializeAsync();
    await AuthenticationService.Instance.SignInAnonymouslyAsync();

    QuickJoinOptions quickJoinOptions = new()
    {
      CreateSession = true,
      Timeout = TimeSpan.FromSeconds(5)
    };

    options.WithDirectNetwork();

    ISession session = await MultiplayerService.Instance.MatchmakeSessionAsync(
      quickJoinOptions,
      options
    );

    return session;
  }

It really feels like there used to be some magic that would maybe set the default endpoint values somewhere when it falls back to host (when Timeout is reached) but this is no longer the case. Is this documented? Is it a bug? Do I have to set this now manually first?

Invalid listen endpoint: 127.0.0.1:7777:7777. Note that the listen endpoint MUST be an IP address (not a hostname).
UnityEngine.Debug:LogError (object)
Unity.Netcode.Transports.UTP.UnityTransport/ConnectionAddressData:get_ListenEndPoint () (at ./Library/PackageCache/com.unity.netcode.gameobjects@02e4aaa4170c/Runtime/Transports/UTP/UnityTransport.cs:283)
Unity.Netcode.Transports.UTP.UnityTransport:StartServer () (at ./Library/PackageCache/com.unity.netcode.gameobjects@02e4aaa4170c/Runtime/Transports/UTP/UnityTransport.cs:1628)
Unity.Netcode.NetworkManager:StartHost () (at ./Library/PackageCache/com.unity.netcode.gameobjects@02e4aaa4170c/Runtime/Core/NetworkManager.cs:1425)
Unity.Services.Multiplayer.NetworkManagerSession/<StartAsync>d__22:MoveNext () (at ./Library/PackageCache/com.unity.services.multiplayer@0f1c83818fad/Runtime/Multiplayer/Modules/Network/Handlers/NetworkHandler/NetworkManagerSession.cs:110)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder:Start<Unity.Services.Multiplayer.NetworkManagerSession/<StartAsync>d__22> (Unity.Services.Multiplayer.NetworkManagerSession/<StartAsync>d__22&)
Unity.Services.Multiplayer.NetworkManagerSession:StartAsync ()
Unity.Services.Multiplayer.GameObjectsNetcodeNetworkHandler/<StartAsync>d__2:MoveNext () (at ./Library/PackageCache/com.unity.services.multiplayer@0f1c83818fad/Runtime/Multiplayer/Modules/Network/Handlers/NetworkHandler/GameObjectsNetcodeNetworkHandler.cs:67)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder:Start<Unity.Services.Multiplayer.GameObjectsNetcodeNetworkHandler/<StartAsync>d__2> (Unity.Services.Multiplayer.GameObjectsNetcodeNetworkHandler/<StartAsync>d__2&)
Unity.Services.Multiplayer.GameObjectsNetcodeNetworkHandler:StartAsync (Unity.Services.Multiplayer.NetworkConfiguration)
Unity.Services.Multiplayer.NetworkModule:StartNetworkHandlerAsync (Unity.Services.Multiplayer.NetworkConfiguration) (at ./Library/PackageCache/com.unity.services.multiplayer@0f1c83818fad/Runtime/Multiplayer/Modules/Network/NetworkModule.cs:550)
Unity.Services.Multiplayer.NetworkModule/<StartNetworkWithOptionsAsync>d__64:MoveNext () (at ./Library/PackageCache/com.unity.services.multiplayer@0f1c83818fad/Runtime/Multiplayer/Modules/Network/NetworkModule.cs:326)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder:Start<Unity.Services.Multiplayer.NetworkModule/<StartNetworkWithOptionsAsync>d__64> (Unity.Services.Multiplayer.NetworkModule/<StartNetworkWithOptionsAsync>d__64&)
Unity.Services.Multiplayer.NetworkModule:StartNetworkWithOptionsAsync ()
Unity.Services.Multiplayer.NetworkModule/<StartDirectNetworkAsync>d__78:MoveNext () (at ./Library/PackageCache/com.unity.services.multiplayer@0f1c83818fad/Runtime/Multiplayer/Modules/Network/NetworkModule.cs:639)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder:Start<Unity.Services.Multiplayer.NetworkModule/<StartDirectNetworkAsync>d__78> (Unity.Services.Multiplayer.NetworkModule/<StartDirectNetworkAsync>d__78&)
Unity.Services.Multiplayer.NetworkModule:StartDirectNetworkAsync (Unity.Services.Multiplayer.DirectNetworkOptions)
NetworkSessionManager/<JoinOrCreateMatchmakeSessionWithDirect>d__48:MoveNext () (at Assets/Scripts/Networking/NetworkSessionManager.cs:679)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Multiplayer.ISession>:SetResult (Unity.Services.Multiplayer.ISession)
Unity.Services.Multiplayer.WrappedMultiplayerService/<MatchmakeSessionAsync>d__24:MoveNext () (at ./Library/PackageCache/com.unity.services.multiplayer@0f1c83818fad/Runtime/Multiplayer/WrappedMultiplayerService.cs:129)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Multiplayer.SessionHandler>:SetResult (Unity.Services.Multiplayer.SessionHandler)
Unity.Services.Multiplayer.SessionManager/<QuickJoinAsync>d__21:MoveNext () (at ./Library/PackageCache/com.unity.services.multiplayer@0f1c83818fad/Runtime/Multiplayer/Session/SessionManager.cs:202)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Multiplayer.SessionHandler>:SetResult (Unity.Services.Multiplayer.SessionHandler)
Unity.Services.Multiplayer.SessionManager/<CreateAsync>d__17:MoveNext () (at ./Library/PackageCache/com.unity.services.multiplayer@0f1c83818fad/Runtime/Multiplayer/Session/SessionManager.cs:88)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Multiplayer.SessionHandler>:SetResult (Unity.Services.Multiplayer.SessionHandler)
Unity.Services.Multiplayer.SessionManager/<SetupSessionAsync>d__24:MoveNext () (at ./Library/PackageCache/com.unity.services.multiplayer@0f1c83818fad/Runtime/Multiplayer/Session/SessionManager.cs:271)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder:SetResult ()
Unity.Services.Multiplayer.SessionHandler/<SavePropertiesAsync>d__153:MoveNext () (at ./Library/PackageCache/com.unity.services.multiplayer@0f1c83818fad/Runtime/Multiplayer/Session/SessionHandler.cs:1057)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder:SetResult ()
Unity.Services.Multiplayer.LobbyHandler/<UpdateLobbyAsync>d__89:MoveNext () (at ./Library/PackageCache/com.unity.services.multiplayer@0f1c83818fad/Runtime/Multiplayer/Lobby/LobbyHandler.cs:487)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Lobbies.Models.Lobby>:SetResult (Unity.Services.Lobbies.Models.Lobby)
Unity.Services.Lobbies.Internal.WrappedLobbyService/<UpdateLobbyAsync>d__32:MoveNext () (at ./Library/PackageCache/com.unity.services.multiplayer@0f1c83818fad/Runtime/Lobbies/SDK/WrappedLobbyService.cs:379)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Lobbies.Response`1<Unity.Services.Lobbies.Models.Lobby>>:SetResult (Unity.Services.Lobbies.Response`1<Unity.Services.Lobbies.Models.Lobby>)
Unity.Services.Lobbies.Internal.WrappedLobbyService/<TryCatchRequest>d__42`2<Unity.Services.Lobbies.Lobby.UpdateLobbyRequest, Unity.Services.Lobbies.Models.Lobby>:MoveNext () (at ./Library/PackageCache/com.unity.services.multiplayer@0f1c83818fad/Runtime/Lobbies/SDK/WrappedLobbyService.cs:609)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Lobbies.Response`1<Unity.Services.Lobbies.Models.Lobby>>:SetResult (Unity.Services.Lobbies.Response`1<Unity.Services.Lobbies.Models.Lobby>)
Unity.Services.Lobbies.Apis.Lobby.LobbyApiClient/<UpdateLobbyAsync>d__23:MoveNext () (at ./Library/PackageCache/com.unity.services.multiplayer@0f1c83818fad/Runtime/Lobbies/Apis/LobbyApi.cs:705)
System.Threading.Tasks.AwaitTaskContinu

I want to share the Cursor AI LLM barf that resolved this issue and wonder if anyone understands why I had to do this

 /// <summary>
  /// Publish host connection info to the session so clients can connect. Call when we're host before StartOnlineMultiplayerGame (Custom Game path).
  /// </summary>
  /// <param name="session">The session we're host of.</param>
  /// <param name="settings">Address and port the host is listening on.</param>
  public async Task PublishHostConnectionInfoAsync(ISession session, NetworkSettings settings)
  {
    if (!session.IsHost)
    {
      return;
    }

    IHostSession hostSession = session.AsHost();
    hostSession.SetProperty(
      SessionPropertyKeyHostAddress,
      new SessionProperty(settings.ipAddress, VisibilityPropertyOptions.Public, PropertyIndex.String2)
    );
    hostSession.SetProperty(
      SessionPropertyKeyHostPort,
      new SessionProperty(
        settings.port.ToString(),
        VisibilityPropertyOptions.Public,
        PropertyIndex.String3
      )
    );
    await hostSession.SavePropertiesAsync();
  }

  /// <summary>
  /// Client: wait for host to publish HostAddress/HostPort, then return network settings for InitializeAsClient (same as Join by IP).
  /// </summary>
  /// <param name="session">The session we joined (we're client).</param>
  /// <param name="timeoutMs">Max time to wait for host to publish.</param>
  /// <returns>Network settings for InitializeAsClient, or null if timeout.</returns>
  public async Task<NetworkSettings> GetHostConnectionInfoFromSessionAsync(
    ISession session,
    int timeoutMs = 5000
  )
  {
    int elapsed = 0;
    const int pollIntervalMs = 200;
    while (elapsed < timeoutMs)
    {
      if (
        session.Properties != null
        && session.Properties.TryGetValue(SessionPropertyKeyHostAddress, out SessionProperty addrProp)
        && !string.IsNullOrEmpty(addrProp.Value)
        && session.Properties.TryGetValue(SessionPropertyKeyHostPort, out SessionProperty portProp)
        && !string.IsNullOrEmpty(portProp.Value)
        && ushort.TryParse(portProp.Value, out ushort port)
      )
      {
        return new NetworkSettings
        {
          ipAddress = addrProp.Value,
          port = port,
          local = false
        };
      }

      await Task.Delay(pollIntervalMs);
      elapsed += pollIntervalMs;
    }

    return null;
  }

It included comments like

    // When we're host we do NOT call StartDirectNetworkAsync: the package overwrites ServerListenAddress to
    // "127.0.0.1:7777" which makes UnityTransport build invalid endpoint "127.0.0.1:7777:7777". We use the
    // same path as Custom Game: caller will PublishHostConnectionInfoAsync then StartOnlineMultiplayerGame
    // (InitializeAsHost) so we control the transport.

It seems to think the new implementation is altering the port or ip address, it definitely feels like a bug.

When you upgraded Unity to 6.3, did you also perchance update some of your packages as well? In particular what were the versions of com.unity.netcode.gameobjects and com.unity.services.multiplayer before/after the upgrade? You can look at the history of your project’s Packages/manifest.json file to find this out.

Actually I think I’ve found the problem. If I’m right, it’s a bug introduced in version 2.1.0 of com.unity.services.multiplayer that only triggers if you’re using NGO version 2.8.0 or later. Could you try either downgrading the ‘Multiplayer Services’ package to version 2.0.0 or alternatively downgrading NGO to version 2.7.0?

I actually didn’t update my packages initially. The bug was immediate after upgrading Unity to 6.3 from 6.2. I upgraded all packages after and am still faced with the same issue.

Anyways this is before when I was on 6.2 and all was well. I don’t know if all of these are external packages, but just to re-iterate, the result was form updating Unity from 6.2 to 6.3, not external packages.

“com.unity.multiplayer.center”: “1.0.0”,
“com.unity.multiplayer.playmode”: “1.6.1”,
“com.unity.multiplayer.tools”: “2.2.6”,
“com.unity.multiplayer.widgets”: “1.0.1”,
“com.unity.netcode.gameobjects”: “2.2.0”,
“com.unity.services.multiplayer”: “1.1.0”,

That’s weird, because the code causing the error is coming straight from the packages. I don’t see how the engine version could impact the behavior here. Maybe some packages were updated when you upgraded to 6.3?

In any case I’ve identified a bug that would result in exactly the error you observed. I’m working on releasing a fix, but until then downgrading either NGO to version 2.7.0 or ‘Multiplayer Services’ to version 2.0.0 should avoid the issue.

| Maybe some packages were updated when you upgraded to 6.3?

→ Maybe, I have no idea.. Although I did manually upgrade everything afterwords, maybe it brought some stuff up to an intermediate version. The reason I thought it was 6.3 was I saw a change in my Game.unity scene to ClientBindPort to 0 which did not exist before and figured that could be it.

Thanks for looking in to this. I can keep my hack for now.

I am having the same issue.

The error is propagating from the ListenEndPoint getter in the ConnectionAddressData struct. Looking through the stack trace, the ServerListenAddress property seems to include the port as part of the string. So, for example, $"{ServerListenAddress}:{Port}" results in the string 127.0.0.1:7777:7777 (port is appended twice, which would result in an invalid listen endpoint). I don’t know if this is by intention, but it seems very odd if it is.

In the Cursor-generated snippet, the Host manually publishes the SessionPropertyKeyHostAddress and SessionPropertyKeyHostPort properties. The client reads those properties and then creates its own NetworkSettings struct. I think this side-steps the issue of the port being appended twice (because you create the NetworkSettings with valid data manually), which results in the Direct Connection actually working.

This is just what I speculate is causing the issue. Anyways, I downgraded to a 1.x version of com.unity.services.multiplayer and a <2.8.0 version of NGO, as I was using these previously. Everything seems to work fine now.

Yes, appending the port twice is indeed not intentional. It’s a bug in the com.unity.services.multiplayer package (introduced in version 2.1.0) in code that is only compiled if NGO 2.8.0 or above is present. So downgrading either of these packages should provide a workaround.

I made a fix to the package and it will be released in the next version of com.unity.services.multiplayer, though at this point I can’t say exactly when that will be.

This appears to still be an issue as of 2.13, Can you confirm. Is there a fix coming?

The fix should have landed in version 2.2.0. Latest version is 2.2.4. Can you try updating to that?