egametang/ET · error · Exception

service discovery endpoint unavailable after resolve, reques

Error message

service discovery endpoint unavailable after resolve, request: {requestName}, scene: {self.Root().Name}

What it means

Thrown at line 608 in ForwardToDiscoveryByFailoverCore: EnsureReadyForRequestAsync returned without throwing (so the agent is alive and considered ready) yet ServiceDiscoveryActorId is still default or IsReady() is false. This is an inconsistent-state failure — the readiness machinery believes resolution succeeded but no concrete master endpoint was populated, so there is nowhere to send the request.

Source

Thrown at Packages/cn.etetet.servicediscovery/Scripts/Hotfix/Server/ServiceDiscoveryAgentSystem.cs:608

            {
                self = selfRef;
                if (self == null)
                {
                    throw new Exception("service discovery agent disposed");
                }

                if (self.ServiceDiscoveryActorId == default)
                {
                    await self.EnsureReadyForRequestAsync(requestName);
                    self = selfRef;
                    if (self == null)
                    {
                        throw new Exception("service discovery agent disposed");
                    }

                    if (!self.IsReady() || self.ServiceDiscoveryActorId == default)
                    {
                        throw new Exception(
                            $"service discovery endpoint unavailable after resolve, request: {requestName}, scene: {self.Root().Name}");
                    }

                    continue;
                }

                ActorId targetActorId = self.ServiceDiscoveryActorId;
                try
                {
                    IResponse rawResponse = await self.MessageSender.Call(targetActorId, request);
                    self = selfRef;
                    if (self == null)
                    {
                        throw new Exception("service discovery agent disposed");
                    }

                    if (rawResponse is not T response)
                    {

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Eliminate concurrent endpoint mutation during a request: serialize invalidation and forwarding.
  2. Re-trigger registration and retry the request once at the caller level when this specific message appears.
  3. Audit SwitchToEndpoint / registration to confirm ServiceDiscoveryActorId and AgentRegistered status are set atomically.
Defensive patterns

Strategy: retry

Validate before calling

if (agent.ServiceDiscoveryActorId == default || !agent.IsReady())
{
    // inconsistent ready state; do not forward
}

Try / catch

catch (Exception e) when (e.Message.Contains("endpoint unavailable after resolve"))
{
    // retry once after triggering re-register
    agent?.InvalidateEndpointAndTriggerBackgroundRegister("caller-retry");
}

Prevention

When it happens

Trigger: EnsureReadyForRequestAsync completed (agent alive, retries OK) but the endpoint field was cleared between the ensure call and the check (e.g. InvalidateEndpointAndTriggerBackgroundRegister ran concurrently), or IsReady()'s definition (ServiceDiscoveryActorId != default AND AgentRegistered) is partially satisfied. Also reachable if SwitchToEndpoint never set the actor id.

Common situations: Concurrent endpoint invalidation racing with a ready check; a master that flaps (registers then immediately drops) so the agent flips between ready and not; a bug where registration sets AgentRegistered but ServiceDiscoveryActorId stays default.

Related errors


AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13). Data as JSON: /api/errors/73fe5b4c989cda8b. Report an issue: GitHub.