babalae/better-genshin-impact · error · ArgumentNullException

实时任务名称不能为空

Error message

实时任务名称不能为空

What it means

ArgumentNullException thrown by Dispatcher.AddTrigger at line 92 when RealtimeTimer.Name is null or empty. RealtimeTimer has a parameterless constructor that leaves Name null (the field is `string?`); only the (string name) and (string name, dynamic config) constructors populate it. TaskTriggerDispatcher.AddTrigger keys on the name, so an empty name cannot route the trigger.

Source

Thrown at BetterGenshinImpact/Core/Script/Dependence/Dispatcher.cs:92

    }

    /// <summary>
    /// 添加实时任务,不会清理之前的任务
    /// </summary>
    /// <param name="timer"></param>
    /// <exception cref="ArgumentNullException"></exception>
    /// <exception cref="ArgumentException"></exception>
    public void AddTrigger(RealtimeTimer timer)
    {
        var realtimeTimer = timer;
        if (realtimeTimer == null)
        {
            throw new ArgumentNullException(nameof(realtimeTimer), "实时任务对象不能为空");
        }

        if (string.IsNullOrEmpty(realtimeTimer.Name))
        {
            throw new ArgumentNullException(nameof(realtimeTimer.Name), "实时任务名称不能为空");
        }

        if (!TaskTriggerDispatcher.Instance().AddTrigger(realtimeTimer.Name, realtimeTimer.Config))
        {
            throw new ArgumentException($"添加实时任务失败: {realtimeTimer.Name}", nameof(realtimeTimer.Name));
        }
    }

    public async Task RunTask(SoloTask soloTask, CancellationTokenSource customCts)
    {
        // 创建链接的取消令牌源,任何一个取消都会触发
        CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(
            customCts.Token,
            CancellationContext.Instance.Cts.Token);
        await RunTask(soloTask, linkedCts.Token);
    }

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Always use a name-bearing constructor: `new RealtimeTimer('AutoSkip')`.
  2. If using the no-arg ctor, set `timer.Name = '...'` before AddTrigger.
  3. Validate the name string in JS before calling AddTrigger.

Example fix

// before (JS)
const t = new RealtimeTimer();
dispatcher.AddTrigger(t); // throws: Name is null

// after (JS)
const t = new RealtimeTimer('AutoSkip');
dispatcher.AddTrigger(t);
Defensive patterns

Strategy: validation

Validate before calling

// JS side
if (!timer.Name) throw new Error('RealtimeTimer.Name is required');
dispatcher.AddTrigger(timer);

Type guard

// JS
function hasTimerName(t) { return t != null && typeof t.Name === 'string' && t.Name.length > 0; }

Prevention

When it happens

Trigger: JS does `new RealtimeTimer()` (no-arg ctor) then AddTrigger without setting .Name. Or `new RealtimeTimer('')` / `new RealtimeTimer(null)`. The (name, config) constructor was used but name was an empty string literal.

Common situations: Script author used the default constructor and forgot `.Name = '...'`. A variable intended to hold the name was undefined when the constructor ran.

Related errors


AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13). Data as JSON: /api/errors/bc970462541cb72d. Report an issue: GitHub.