jdx/mise · error

task {} cache outputs require at least one non-excluded patt

Error message

task {} cache outputs require at least one non-excluded pattern

What it means

validate_config takes the task's output patterns and computes output_glob_patterns(&patterns) — the list with exclusions ('!...') filtered out. If patterns is non-empty but every entry is an exclusion, there is nothing to save and the config is rejected with 'cache outputs require at least one non-excluded pattern'.

Source

Thrown at src/task/task_cache.rs:1226

        bail!(
            "task {} cache requires explicit outputs or outputs = []",
            task.name
        );
    }
    if let Some(command) = task.cache.as_ref().and_then(|cache| {
        cache
            .command_inputs
            .iter()
            .find(|command| command.trim().is_empty())
    }) {
        bail!(
            "task {} cache command input must not be empty: {command:?}",
            task.name
        );
    }
    let patterns = task.outputs.patterns();
    if !patterns.is_empty() && output_glob_patterns(&patterns).is_empty() {
        bail!(
            "task {} cache outputs require at least one non-excluded pattern",
            task.name
        );
    }
    for output in &patterns {
        let path = if let Some(body) = output.strip_prefix('!') {
            PathBuf::from(body)
        } else if let Some(body) = output.strip_prefix("\\!") {
            PathBuf::from(format!("!{body}"))
        } else {
            PathBuf::from(&output)
        };
        ensure_safe_relative(&path).wrap_err_with(|| {
            format!(
                "task {} cache output must stay within {}: {output}",
                task.name,
                root.display()
            )

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Add at least one inclusion pattern, e.g. outputs = ["dist/**", "!dist/tmp/**"]
  2. If the task truly writes nothing, use outputs = [] instead of exclusion-only lists
  3. Lint task configs for outputs arrays containing only '!'-prefixed entries

Example fix

# before
[tasks.pack]
outputs = ["!dist/*.tmp"]

# after
[tasks.pack]
outputs = ["dist/**", "!dist/*.tmp"]
Defensive patterns

Strategy: validation

Validate before calling

python3 - <<'EOF'
import tomllib, sys
cfg = tomllib.load(open('mise.toml','rb'))
for name, t in cfg.get('tasks', {}).items():
    outs = [str(o) for o in t.get('outputs', [])]
    if outs and all(o.lstrip('\\').startswith('!') for o in outs):
        sys.exit(f'{name}: outputs contains only exclusions')
print('ok')
EOF

Prevention

When it happens

Trigger: outputs = ["!tmp/**"] or outputs = ["!*.log", "!cache/**"] — only negated patterns, so output_glob_patterns returns an empty vec while patterns is not empty.

Common situations: Starting from an exclusion list intending to add includes later; refactoring outputs and accidentally deleting the inclusion lines; misunderstanding that '!' entries only filter, never select.

Related errors


AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22). Data as JSON: /api/errors/3318f5a374c45638. Report an issue: GitHub.