egametang/ET · critical · Exception

fiber local slot exhausted, zone: {zone}, nextLocalSlot: {lo

Error message

fiber local slot exhausted, zone: {zone}, nextLocalSlot: {localSlot}, dynamic range: [{FiberIdHelper.DynamicLocalSlotStart}, {FiberIdHelper.ReservedLocalSlotStart - 1}]

What it means

AllocateLocalSlot (FiberManager line 200) throws when the dynamic local-slot counter for a zone reaches ReservedLocalSlotStart (int.MaxValue - 15). Slots are allocated per zone starting at DynamicLocalSlotStart (100000) and monotonically incremented; the code never recycles freed slots, so exhaustion implies an unbounded fiber-creation leak within one process lifetime.

Source

Thrown at Packages/cn.etetet.core/Scripts/Core/Share/World/Fiber/FiberManager.cs:200

            catch (Exception e)
            {
                throw new Exception($"create fiber error: {fiberId} {sceneType}", e);
            }
        }

        private int AllocateLocalSlot(int zone)
        {
            FiberIdHelper.ValidateZone(zone);

            lock (this.localSlotLock)
            {
                int localSlot = this.nextLocalSlotByZone.TryGetValue(zone, out int nextLocalSlot)
                        ? nextLocalSlot
                        : FiberIdHelper.DynamicLocalSlotStart;

                if (localSlot >= FiberIdHelper.ReservedLocalSlotStart)
                {
                    throw new Exception(
                        $"fiber local slot exhausted, zone: {zone}, nextLocalSlot: {localSlot}, dynamic range: [{FiberIdHelper.DynamicLocalSlotStart}, {FiberIdHelper.ReservedLocalSlotStart - 1}]");
                }

                this.nextLocalSlotByZone[zone] = localSlot + 1;
                return localSlot;
            }
        }

        /// <summary>
        /// 创建纤程
        /// </summary>
        /// <param name="schedulerType">纤程调度器,-1: 主线程,-2: 当前线程,-3: 线程池, 其它: 纤程</param>
        /// <param name="rootId"></param>
        /// <param name="zone">区</param>
        /// <param name="sceneType">场景类型</param>
        /// <param name="name">纤程名称</param>
        /// <param name="parent"></param>
        /// <returns>纤程id</returns>

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Find and fix the fiber leak - ensure every CreateFiber has a matching Dispose/teardown and that no update loop spawns unbounded fibers.
  2. Pool/reuse fibers for repeated transient work instead of allocating new ones.
  3. If legitimate long-lived load needs many fibers, restart the process on a schedule (the slot space is per-process and not recycled).
  4. Add instrumentation counting live fibers per zone to detect the leak early.
Defensive patterns

Strategy: try-catch

Try / catch

try { return fiberManager.CreateFiber(...); }
catch (Exception e) when (e.Message.Contains("fiber local slot exhausted"))
{ Log.Error($"fiber slot exhaustion - likely fiber leak, restarting zone: {e}"); throw; }

Prevention

When it happens

Trigger: Creating more than ~2.1 billion fibers in a single zone (dynamic range 100000..int.MaxValue-16) without restart - effectively a runaway loop that spawns fibers and never disposes them, or fibers created in a hot loop without pooling.

Common situations: A server that repeatedly creates transient fibers per request/message without tearing them down, a reconnect storm, a bug creating a fiber inside an update loop, or an extremely long-lived process accumulating fibers.

Related errors


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