babalae/better-genshin-impact · error · ArgumentNullException
实时任务对象不能为空
Error message
实时任务对象不能为空
What it means
ArgumentNullException thrown by Dispatcher.AddTrigger at line 87 when the RealtimeTimer argument is null. Dispatcher is a ClearScript host object exposed to JS scripts; this guard fires when JS calls dispatcher.addTrigger(null)/undefined. The preceding `var realtimeTimer = timer` assignment is a no-op — the null check is what protects TaskTriggerDispatcher from receiving a null trigger.
Source
Thrown at BetterGenshinImpact/Core/Script/Dependence/Dispatcher.cs:87
/// 清理所有实时任务
/// </summary>
public void ClearAllTriggers()
{
TaskTriggerDispatcher.Instance().ClearTriggers();
}
/// <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,View on GitHub (pinned to a7cb36712d)
Solutions
- Construct the timer before calling: `const t = new RealtimeTimer('AutoPick'); dispatcher.AddTrigger(t);`
- Add a JS-side null check before calling AddTrigger.
- Use the RealtimeTimer constructor that takes a name to guarantee a usable object.
Example fix
// before (JS)
dispatcher.AddTrigger(maybeTimer);
// after (JS)
if (!maybeTimer) { throw new Error('timer must be constructed before AddTrigger'); }
dispatcher.AddTrigger(maybeTimer); Defensive patterns
Strategy: validation
Validate before calling
// JS side
function addTriggerSafe(timer) {
if (timer == null) throw new Error('RealtimeTimer must be constructed before AddTrigger');
dispatcher.AddTrigger(timer);
} Type guard
// JS duck-type check
function isRealtimeTimer(v) {
return v != null && typeof v === 'object' && typeof v.Name !== 'undefined';
} Prevention
- Always construct RealtimeTimer via its name-bearing constructor before calling AddTrigger.
- Add a JS wrapper that null-checks host objects before forwarding to the dispatcher.
- Initialize timer variables at declaration, not in conditional branches.
When it happens
Trigger: JS calls `dispatcher.AddTrigger(null)` or `dispatcher.AddTrigger(undefined)`. A factory function in JS returns undefined and its result is passed straight through. A conditional branch that should have built a RealtimeTimer was skipped.
Common situations: JS script author forgot to construct the RealtimeTimer object. A typo or wrong variable name passed undefined. A feature flag toggled off left the timer variable unset.
Related errors
AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13).
Data as JSON: /api/errors/26143d4b7aaade3f.
Report an issue: GitHub.