itsfatduck/optimizerDuck · error · StepExecutionException

Scheduled task verify failed at

Error message

Scheduled task verify failed at {FullPath}: expected enabled={OriginalEnabled}, actual={state == TaskEnabledState.Enabled}

What it means

ScheduledTaskRevertStep.ExecuteAsync throws this when the task state was queried successfully but the actual Enabled/Disabled state does not match OriginalEnabled recorded at apply time. The restore command ran, but read-back verification proves the effect did not stick.

Solutions

  1. Re-run the revert; transient locks (task currently running) often clear once the task stops.
  2. Stop the running task instance first (schtasks /end /tn <path>) then retry.
  3. Check for Group Policy or vendor software re-applying the state and disable that source before reverting.
  4. Manually set the task state with schtasks /change /tn <path> /enable|/disable to match the desired original state, then clean up the revert file if the state is now correct.

Example fix

// before
task.Enabled = OriginalEnabled; // may not stick while task is running
// after
if (task.State == TaskState.Running) task.Stop();
task.Enabled = OriginalEnabled;
task.RegisterChanges();
Defensive patterns

Strategy: retry

Validate before calling

var state = ScheduledTaskService.GetTaskEnabledState(fullPath, logger);
if (state.State is TaskEnabledState.Unknown) return; // nothing verifiable

Try / catch

catch (StepExecutionException ex) when (ex.Message.Contains("expected enabled="))
{ await Task.Delay(1000); await RetryFailedStepsWithResultsAsync(); }

Prevention

When it happens

Trigger: task.Enabled = true/false silently failed (e.g. task instance currently running with 'do not start on demand' semantics), Group Policy or another process re-disabled/re-enabled the task after the set, or the wrong task was targeted. The re-query returns Enabled/Disabled but opposite to OriginalEnabled.

Common situations: Bloatware task recreated by vendor software running in the background; corporate GPO forcing task state; task locked while running so the state change is deferred; mismatch between the id's stored OriginalEnabled and reality after manual changes.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of itsfatduck/optimizerDuck@36acf585ae (2026-09-13). Data as JSON: /api/errors/e13ddbba77e9f78d. Report an issue: GitHub.

Appendix: source

Thrown at optimizerDuck/Domain/Revert/Steps/ScheduledTaskRevertStep.cs:57

        var opCall = new OpCall { Logger = logger };
        var result = OriginalEnabled
            ? ScheduledTaskService.EnableTask(opCall, FullPath)
            : ScheduledTaskService.DisableTask(opCall, FullPath);

        if (!result.Ok)
            throw new StepExecutionException(result.Error ?? Description, result.ErrorDetail);

        // a missing task has nothing to restore; anything else must verify positively.
        var state = ScheduledTaskService.GetTaskEnabledState(FullPath, opCall.Logger);
        if (state is TaskEnabledState.NotFound)
            return Task.FromResult(true);
        if (state is not (TaskEnabledState.Enabled or TaskEnabledState.Disabled))
            throw new StepExecutionException(
                $"Scheduled task verify failed at {FullPath}: could not query the task state.",
                null
            );
        if ((state == TaskEnabledState.Enabled) != OriginalEnabled)
            throw new StepExecutionException(
                $"Scheduled task verify failed at {FullPath}: expected enabled={OriginalEnabled}, actual={state == TaskEnabledState.Enabled}",
                null
            );

        return Task.FromResult(true);
    }

    /// <inheritdoc />
    public JObject ToData()
    {
        return new JObject
        {
            [nameof(FullPath)] = FullPath,
            [nameof(OriginalEnabled)] = OriginalEnabled,
        };
    }

    /// <summary>

View on GitHub (pinned to 36acf585ae)