egametang/ET · error · Exception

add cancel token is null

Error message

add cancel token is null

What it means

Thrown by ETCancellationTokenHelper.AddCancel(this ETTask, ETCancellationToken) when addCancelToken is null. The extension chains a new cancellation source onto the task's context, so a null token cannot be wired up and is rejected up front with a plain Exception. This is the ET coroutine framework's precondition guard.

Source

Thrown at Packages/cn.etetet.core/Scripts/Core/Share/ETCancellationToken/ETCancellationTokenHelper.cs:44

            }

            // 这里用了Fiber.Instance是因为我知道有什么后果, 你们千万不能乱用这个Fiber.Instance
            await Fiber.Instance.Root.TimerComponent.WaitAsync(afterTimeCancel);
            if (self.IsCancel())
            {
                return;
            }
            self.Cancel();
        }
        
        /// <summary>
        /// 增加一个canceltoken,可以用新增的canceltoken取消协程,当然也可以用老的取消
        /// </summary>
        public static async ETTask AddCancel(this ETTask task, ETCancellationToken addCancelToken)
        {
            if (addCancelToken == null)
            {
                throw new Exception("add cancel token is null");
            }
            ETCancellationToken cancelToken = await ETTask.GetContextAsync<ETCancellationToken>();
            
            cancelToken?.Add(addCancelToken.Cancel);
            
            await task.NewContext(addCancelToken);
        }
        
        /// <summary>
        /// 增加一个canceltoken,可以用新增的canceltoken取消协程,当然也可以用老的取消
        /// </summary>
        public static async ETTask<T> AddCancel<T>(this ETTask<T> task, ETCancellationToken addCancelToken)
        {
            if (addCancelToken == null)
            {
                throw new Exception("add cancel token is null");
            }
            

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Construct the token before calling: var token = new ETCancellationToken(); await task.AddCancel(token);
  2. For no-cancel cases, simply await the task directly instead of calling AddCancel(null).
  3. Prefer the TimeoutAsync(this ETTask, long afterTimeCancel) overload which creates the token internally.

Example fix

// before
await task.AddCancel(null); // throws

// after
await task.AddCancel(new ETCancellationToken());
Defensive patterns

Strategy: validation

Validate before calling

// Construct the token before calling AddCancel.
if (addCancelToken == null) addCancelToken = new ETCancellationToken();
await task.AddCancel(addCancelToken);

Type guard

static bool IsValidToken(ETCancellationToken t) => t != null && !t.IsDispose();

Prevention

When it happens

Trigger: Calling task.AddCancel(null); passing a token field that was never assigned; reusing a token after it was disposed and set to null; calling the overload that creates a token implicitly but forwarding null by mistake.

Common situations: Forgetting to construct ETCancellationToken before calling AddCancel/TimeoutAsync; refactors that removed token creation; conditional code paths that pass null when no timeout is desired (should skip the call instead).

Related errors


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