jdx/mise · error

scheduled task name contains characters that cannot be…

Error message

scheduled task name {name:?} contains characters that cannot be queried

What it means

On Windows, mise queries scheduled tasks by shelling out to schtasks via a PowerShell wrapper. Because the task name is interpolated into a PowerShell command, names containing characters outside [A-Za-z0-9._-] are rejected up front to prevent injection and malformed queries. This is a deliberate safety/validation bail, not a lookup miss.

Solutions

  1. Rename the scheduled task in mise.toml (or wherever it is declared) to use only ASCII letters, digits, '.', '_' and '-'
  2. If the name comes from a variable or template, sanitize/normalize it to the allowed character set before it reaches the config
  3. If you believe the character is safe, file an issue to extend the whitelist; do not work around it by crafting names with escapes

Example fix

// before
[scheduled_task.backup-job.daily]
cron = "0 3 * * *"
// after
[scheduled_task.backup_job_daily]
cron = "0 3 * * *"
Defensive patterns

Strategy: validation

Validate before calling

fn valid_task_name(name: &str) -> bool {
    let name = name.strip_prefix("mise\\").unwrap_or(name);
    !name.is_empty()
        && name.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '.' | '_' | '-'))
}
// assert!(valid_task_name("backup_daily"));

Type guard

fn is_safe_task_name(s: &str) -> bool {
    s.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '.' | '_' | '-'))
}

Prevention

When it happens

Trigger: Calling mise scheduled-task status/exists/apply (via src/system/scheduled_tasks.rs::query) with a task name that has a path separator, space, backslash prefix beyond the stripped 'mise\\', unicode characters, or shell metacharacters.

Common situations: A mise.toml [scheduled_task] name was written with a space or slash (e.g. "my task", "backup/daily"), or a task name derived from a path or env var picks up unexpected characters; also backslash-heavy Windows naming habits colliding with the strict whitelist.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/31f675e30807d098. Report an issue: GitHub.

Appendix: source

Thrown at src/system/scheduled_tasks.rs:473

/// The task's state through the Task Scheduler API rather than the
/// localized text `schtasks /query` prints. Prints `MISSING` for an
/// unregistered task and the `TaskState` name otherwise. The name is
/// embedded in the script (arguments after `-Command` are more command
/// text, not `$args`); names are validated to letters, digits, `.`, `_`,
/// and `-` before they get here.
fn query_script(name: &str) -> String {
    format!(
        "$t = Get-ScheduledTask -TaskPath '\\mise\\' -TaskName '{name}' -ErrorAction SilentlyContinue; if ($null -eq $t) {{ 'MISSING' }} else {{ $t.State.ToString() }}"
    )
}

async fn query(task: &str) -> Result<Option<Query>> {
    let name = task.strip_prefix("mise\\").unwrap_or(task);
    if !name
        .chars()
        .all(|c| c.is_ascii_alphanumeric() || matches!(c, '.' | '_' | '-'))
    {
        bail!("scheduled task name {name:?} contains characters that cannot be queried");
    }
    let args = [
        "-NoProfile".to_string(),
        "-NonInteractive".to_string(),
        "-Command".to_string(),
        query_script(name),
    ];
    debug!("$ powershell {}", shell_words::join(&args));
    let mut cmd = tokio::process::Command::new("powershell.exe");
    cmd.args(&args)
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .kill_on_drop(true);
    let output = tokio::time::timeout(SCHTASKS_TIMEOUT, cmd.output())
        .await
        .map_err(|_| eyre!("querying scheduled task {task} timed out"))??;
    if !output.status.success() {

View on GitHub (pinned to 533346cc37)