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.

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.

Appendix: 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)