babalae/better-genshin-impact · warning · NormalEndException

请先在启动页,启动截图器再使用本功能

Error message

请先在启动页,启动截图器再使用本功能

What it means

A NormalEndException (with a preceding Toast.Warning) thrown by TaskRunner.Init() when TaskContext.Instance().IsInitialized is false. It marks the task as gracefully ended rather than crashed: the toast tells the user to start the screenshotter on the startup page first. NormalEndException is the project's convention for an expected, user-facing termination.

Source

Thrown at BetterGenshinImpact/GameTask/TaskRunner.cs:154

        if (CancellationContext.Instance.IsCancellationRequested)
        {
            _logger.LogInformation("独立任务在启动阶段被取消: {Name}", soloTask.Name);
            CancellationContext.Instance.Clear();
            return;
        }
        
        await Task.Run(() => RunCurrentAsync(
            async () => await soloTask.Start(CancellationContext.Instance.Cts.Token),
            resetCancellationContext: false,
            clearCancellationContextOnLockFailure: true));
    }

    public void Init()
    {
        if (!TaskContext.Instance().IsInitialized)
        {
            UIDispatcherHelper.Invoke(() => { Toast.Warning("请先在启动页,启动截图器再使用本功能"); });
            throw new NormalEndException("请先在启动页,启动截图器再使用本功能");
        }

        // 清空实时任务触发器
        TaskTriggerDispatcher.Instance().ClearTriggers();
        
        // 隐藏地图遮罩
        UIDispatcherHelper.Invoke(() =>
        {
            if (MaskWindow.InstanceNullable() != null)
            {
                if (MaskWindow.Instance().DataContext is MaskWindowViewModel vm)
                {
                    vm.IsInBigMapUi = false;
                }
            }
        });
        VisionContext.Instance().DrawContent.ClearAll(); 
        

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Go to the startup page and start the screenshotter before using any task feature.
  2. If already started, restart BetterGI (the context may be in a bad state).
  3. At the call site, check TaskContext.Instance().IsInitialized and disable/hide the feature until initialized.
  4. Treat NormalEndException as expected termination at the UI boundary (do not log it as an error).

Example fix

// before
TaskRunner.Instance().Init();
// after
if (!TaskContext.Instance().IsInitialized)
{
    Toast.Warning("请先在启动页,启动截图器再使用本功能");
    return;
}
TaskRunner.Instance().Init();
Defensive patterns

Strategy: validation

Validate before calling

if (!TaskContext.Instance().IsInitialized)
{
    Toast.Warning("请先在启动页,启动截图器再使用本功能");
    return;
}

Type guard

static bool IsReady => TaskContext.Instance().IsInitialized;

Try / catch

// NormalEndException is expected termination; handle at the UI boundary
try { TaskRunner.Instance().Init(); }
catch (NormalEndException) { /* user already got a toast */ }

Prevention

When it happens

Trigger: Invoking a solo/realtime task through TaskRunner before the screenshot/capture context has been started on the startup page. Init() is the entry guard before clearing triggers and hiding the mask.

Common situations: Triggering a gameplay automation feature before initializing capture; clicking a task button immediately after app launch; the capture context was disposed or never started.

Related errors


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