moon task debugger
A workflow-oriented diagnostic skill for troubleshooting moon tasks. This is not a reference manual
— it guides you through a structured debugging flow so you can isolate the problem quickly.
For conceptual background, see the moon documentation.
Before you start: Ask the user for the <project>:<task> target to debug. If they haven't
provided a specific target, prompt them for it — the diagnostic flow requires a concrete target to
inspect.
Quick-start: 5-step diagnostic flow
Work through these steps in order. Most issues resolve by step 3.
Step 1: Inspect the resolved task configuration
The first thing to check is whether the task is configured the way the user expects. moon merges
configuration from multiple sources (global tasks, project config, inheritance), so the resolved
result can surprise people.
# Show the fully resolved task config (with inheritance applied)
moon task <project>:<task>
# Machine-readable version for programmatic inspection
moon task <project>:<task> --json
What to verify:
command vs script — if the command contains pipes (|), redirects (>), chained commands
(&&), or complex syntax, it must use script, not command.
inputs — are they too broad (**/* captures everything) or too narrow (missing source files)?
Check state.defaultInputs (true = using default **/*) and state.emptyInputs (true =
explicitly set to []). Both keys are omitted from the JSON entirely when false, as is
state.setRunInCi.
outputs — are they declared for build tasks? Missing outputs means the cache can never hydrate
artifacts. In v2.3+, outputs also affect the default cacheStrategy of any task that depends
on this one (see Step 4).
toolchains — is the correct toolchain(s) assigned? An incorrect toolchain means wrong tool
versions.
deps — are task dependencies correct and complete? In v2.3+, each dep entry can carry a
cacheStrategy (hash / ignored / outputs) that controls whether the dep contributes to this
task's cache hash. If omitted, the default depends on whether the dep declares outputs.
options — check persistent, runInCI, cache, affectedFiles, mutex, timeout,
retryCount, allowFailure, and os.
env — in v2.5+, environment variables can also be inherited from a workspace-level env in
.moon/tasks/**/* (merged into the project's env, project wins), and the project can change the
merge behavior via workspace.mergeStrategies.env. A variable with a surprising value may come
from a layer outside the task.
checks v2.4+ — shell scripts that run before the task. Their type determines the
outcome: a requirement failing makes the task fail, all condition checks passing makes the
task skip, and a fingerprint folds script output into the task hash. A surprising fail,
skip, or cache invalidation often traces back to a check.
tags v2.3+ — labels for grouping tasks. Affects targets like :#quality and MQL
taskTag queries. If a task isn't matched by a #tag target you expected, check this list.
type — build (has outputs), test (default), or run (persistent)
preset — server or utility apply multiple option defaults at once.
Red flags:
command: 'eslint . && prettier --check .' — shell syntax in command is a parse error in v2.
Use script instead.
- Empty
outputs on a build task — cache will never restore artifacts.
inputs: ['**/*'] — too broad, cache invalidates on every change.
- A
persistent task in a deps chain — moon produces a hard error at runtime.
command: 'noop' or nop / no-op — the task is intentionally a no-op and does nothing. moon
treats these specially.
runInCI: 'only' — task runs in CI but NOT locally (common surprise).
runInCI: 'skip' — task is skipped in CI but relationships remain valid.
os set to a platform the user isn't on — the task is rewritten to a passing no-op at build time
(moon task --json shows command: noop with cleared args/outputs).
allowFailure: true — the failure is still recorded and displayed, but the pipeline continues and
moon exits successfully, so it's easy to miss.
- A
condition check present v2.4+ — the task will skip whenever all conditions
pass. A task that "never runs" may have a condition that always passes.
- A
fingerprint check present v2.4+ — its script output is hashed, so volatile output
(timestamps, versions) causes cache misses on every run.
Step 2: Run with maximum verbosity
If the config looks right, run the task with debug logging to see what moon is actually doing under
the hood.
# Debug-level logging with cache bypass
moon run <project>:<task> --log debug --force
# Deep debugging: reveal env vars and stdin passed to the process
MOON_DEBUG_PROCESS_ENV=true MOON_DEBUG_PROCESS_INPUT=true moon run <project>:<task> --log trace --force
What to look for in the logs:
- Toolchain resolution — is the right version of node/deno/bun/etc being used?
- Hash generation — what sources are being hashed?
- Affected status — is the task being skipped because it's "not affected"?
- Process execution — what command is actually being spawned?
Visualize the execution graph to spot dependency issues:
moon action-graph <project>:<task>
moon action-graph <project>:<task> --dot # DOT format (useful for agents)
For all graph commands and output formats, see references/environment-debug.md.
Step 3: Inspect cache state
If the task runs but produces wrong results, or runs when it shouldn't, or doesn't run when it
should, the cache is the likely culprit.
# Inspect a hash manifest to see what inputs were hashed
moon hash <hash>
# Compare two hashes to see what changed between runs
moon hash <hash1> <hash2>
# Short-form hashes work too
moon hash 0b55b234 2388552f
For cache file locations, hash interpretation, and the --force vs --cache off comparison, see
references/cache-issues.md.
Step 4: Diagnose the problem type
Use this table to jump to the right reference:
| Symptom |
Likely cause |
Quick check |
Reference |
| Task doesn't exist |
Inheritance not applied — check inheritedBy conditions in .moon/tasks/**/* against project's toolchains, stack, layer, tags via moon project <name> --json |
moon task <target> --json |
references/config-mistakes.md |
| "Nothing to do" |
--affected + no changes, runInCI: false, or inheritedBy mismatch (global task not inherited) |
Check flags, options.runInCI, and inheritedBy |
references/decision-tree.md |
--affected misses changed files v2.4+ |
Shallow git clone in CI — merge base can't be resolved, so diffs are inaccurate (moon now logs a warning) |
Check clone depth; use full history or --filter=blob:none |
references/decision-tree.md |
| Task fails: "requirement check failed" v2.4+ |
A requirement check script exited non-zero, so the task refuses to run |
moon task <target> --json — inspect checks |
references/config-mistakes.md |
| Task skipped, not affected/CI-related v2.4+ |
All condition checks passed, so the task was intentionally skipped |
moon run <target> --log debug — look for "conditional checks have passed" |
references/config-mistakes.md |
| Task errors on execution |
Wrong command/script, bad toolchain |
moon run <target> --log debug |
references/config-mistakes.md |
| Stale cache (cached when it shouldn't be) |
Inputs too narrow, missing env vars, or dep cacheStrategy: 'ignored' (the v2.3 default for output-less deps) |
moon hash <hash> |
references/cache-issues.md |
| Cache miss (re-runs every time) |
Inputs too broad, volatile outputs, or dep cacheStrategy: 'hash' propagating upstream churn |
moon hash <h1> <h2> |
references/cache-issues.md |
Cache miss from a fingerprint check v2.4+ |
A fingerprint check's script output is volatile (timestamps, PIDs), changing the hash every run |
moon hash <h1> <h2> — look for the check hash |
references/cache-issues.md |
| Outputs not restored after cache hit |
outputs misconfigured; or v2.5+ a daemon-side archive/hydrate failure — swallowed by the main process, logged only by the daemon (a failed hydrate becomes a silent cache miss) |
Check .moon/cache/outputs/; moon daemon logs |
references/cache-issues.md |
| Env var has unexpected value v2.5+ |
Workspace-level env in .moon/tasks/**/* merged in, or workspace.mergeStrategies.env changed the merge behavior |
moon task <target> --json — inspect env |
references/config-mistakes.md |
| Cache behaves differently across git worktrees v2.5+ |
cache.unstable_sharedWorktreeCache shares blobs/manifests via the base checkout's .moon/cache |
Check the setting and MOON_CACHE_SHARED_WORKTREE_CACHE |
references/cache-issues.md |
| New dependency cycle error after upgrading to v2.5 |
Async graph building (now default) validates cycles strictly, per dependency-scope partition |
Set experiments.asyncGraphBuilding: false to confirm |
references/decision-tree.md |
| Build re-runs on every upstream input change v2.3+ |
Dep using default cacheStrategy: 'hash' instead of 'outputs' |
moon task <target> --json — inspect dep entries |
references/cache-issues.md |
Task not matched by #tag target v2.3+ |
Missing tags on the task, or mergeTags dropped them during inheritance |
moon task <target> --json — check tags |
references/config-mistakes.md |
| Task hangs / pipeline stuck |
Persistent task in deps chain (hard error in v2) |
moon action-graph <target> |
references/config-mistakes.md |
| Task is slow |
Dep chain bottleneck, no parallelism |
moon action-graph <target> |
references/decision-tree.md |
| Task does nothing (no-op) |
Command is noop/nop/no-op |
moon task <target> --json |
references/config-mistakes.md |
| Task fails silently |
allowFailure: true hiding errors |
Check options.allowFailure |
references/config-mistakes.md |
| Task skipped locally |
runInCI: 'only' set |
Check options.runInCI |
references/config-mistakes.md |
| Task skipped in CI |
runInCI: false or 'skip' |
Check options.runInCI |
references/config-mistakes.md |
| Mutex contention / deadlock |
Two tasks share same mutex |
Check options.mutex |
references/config-mistakes.md |
| Task times out |
timeout option set too low |
Check options.timeout |
references/config-mistakes.md |
Step 5: Validate the fix
After making changes, verify the fix actually worked:
# Bypass cache to force a fresh run
moon run <project>:<task> --force
# Disable cache entirely (no reads OR writes)
moon run <project>:<task> --cache off
# Verify the resolved config reflects your changes
moon task <project>:<task> --json
--force vs --cache off:
--force ignores existing cache but writes new cache after execution.
--cache off disables caching entirely — no reads, no writes.
For all cache modes, see references/cache-issues.md.
Common mistakes at a glance
These are the issues that come up most often. For details and fixes, see
references/config-mistakes.md.
- Shell syntax in
command — pipes, &&, redirects require script; v2 rejects these as parse
errors.
- Missing
outputs on build tasks — cache can never hydrate artifacts.
- Overly broad
inputs — **/* invalidates cache on every change; be specific.
- Volatile outputs — timestamps or absolute paths in build artifacts cause permanent cache
misses.
- Persistent task in
deps — hard error; tasks named dev/start/serve auto-get server
preset.
--affected vs --force confusion — --affected restricts; --force bypasses cache
(they're opposites).
allowFailure: true hiding errors — the failure is still recorded and displayed, but the
pipeline continues and moon exits successfully; check stderr at
.moon/cache/states/<project>/<task>/stderr.log.
mutex contention — shared mutex serializes tasks; combined with deps can deadlock.
runInCI: 'only' — task silently skips when run locally (most surprising variant).
- Missing outputs flip dep
cacheStrategy v2.3+ — a dep without outputs now
defaults to cacheStrategy: 'ignored'. Downstream tasks stop invalidating on its changes; set
cacheStrategy: 'hash' explicitly to restore the pre-v2.3 default.
- MQL tag fields on task queries are version-dependent — in v2.3–v2.4,
taskTag= and tag=
(alias of projectTag) in moon query tasks --query silently matched nothing (this also broke
task tag glob targets like :#tag-*). Fixed in v2.5: taskTag matches the task's own tags, and
projectTag/tag match the parent project's tags. On older versions, filter task tags with the
--tags flag instead (moon query tasks --tags quality).
- A
checks script silently changes task behavior v2.4+ — a requirement failing
aborts the task, a passing condition skips it, and a fingerprint mixes script output into the
hash. Inspect checks in moon task <target> --json when a task fails, skips, or re-runs for no
obvious reason.
- Shallow git clone breaks
--affected v2.4+ — a shallow clone (depth 1) prevents
moon from resolving the merge base, so affected detection is inaccurate or empty. Use a full
clone, or a blobless partial clone (git clone --filter=blob:none).
- Experiments are now on by default v2.5+ —
asyncGraphBuilding,
asyncAffectedTracking, and nativeFileHashing default to enabled. When bisecting graph,
affected, or hashing oddities, disable the relevant experiment (config or
MOON_EXPERIMENT_*=false) and compare — but also check the user's shell/CI for
MOON_EXPERIMENT_* or MOON_CACHE_* overrides that silently change behavior.
- Daemon archiving/hydration failures are invisible in the main process v2.5+ — with
the daemon enabled, task outputs are archived and hydrated in the background, and failures only
appear in
moon daemon logs. To rule the daemon out, re-run with MOON_DAEMON=false.
- Workspace-level
env is a new inheritance layer v2.5+ — .moon/tasks/**/* files
can define env inherited by all matching projects. Project values win on conflict, unless
workspace.mergeStrategies.env says otherwise (append, prepend, preserve, replace).
When to load references
Each reference file covers a specific problem domain in depth. Load them only when the diagnostic
flow points you there — don't load everything upfront.
| Reference |
When to load |
references/decision-tree.md |
When the symptom doesn't match the quick table above, or you need a systematic walk-through of all possibilities. |
references/cache-issues.md |
When the problem is clearly cache-related: unexpected hits, unexpected misses, outputs not restoring. |
references/config-mistakes.md |
When the task config is wrong: command vs script, inheritance bugs, presets, persistent tasks, affectedFiles, mutex, timeout, retries, runInCI variants, allowFailure, os. |
references/environment-debug.md |
When you need to go deeper with env vars, log levels, trace profiles, or inspection tools. |
1---
2name: debug-task
3description: >-
4 Diagnose and fix moon tasks that are broken, misconfigured, or behaving unexpectedly. Use this
5 skill when a moon task is failing, not running, skipped, hanging, producing stale or wrong output,
6 cached when it shouldn't be, re-running every time when it should be cached, or when outputs are
7 empty or missing after a cache hit. Also covers pipeline hangs and freezes, tasks that only work
8 in CI but not locally (or vice versa), tasks skipped by --affected, and task inheritance not
9 applying to a project. Activate on any mention of "moon run" or "moon task" combined with a
10 problem — errors, stale cache, missing outputs, wrong results, "nothing to do", or unexpected
11 behavior. Also use for task options like persistent, runInCI, allowFailure, affectedFiles, mutex,
12 timeout, or cacheLifetime, and for task checks (requirement, condition, fingerprint) that make a
13 task fail, skip, or re-run, and project-level taskOptions defaults. This skill is for diagnosing
14 existing tasks, not for creating new tasks, setting up workspaces, configuring toolchains, or
15 learning moon concepts.
16license: MIT
17allowed-tools: Bash(moon:*) Read
18compatibility: >-
19 Requires moon >= 2.0.0 CLI installed and a configured moon workspace.
20metadata:
21 moon-version-min: '2.0.0'
22 moon-version-tested: '2.5.0'
23 category: 'debugging'
24 ecosystem: 'moonrepo'
25---2627
28# moon task debugger
29
30A workflow-oriented diagnostic skill for troubleshooting moon tasks. This is not a reference manual
31— it guides you through a structured debugging flow so you can isolate the problem quickly.
32
33For conceptual background, see the [moon documentation](https://moonrepo.dev/docs).
34
35**Before you start:** Ask the user for the `<project>:<task>` target to debug. If they haven't
36provided a specific target, prompt them for it — the diagnostic flow requires a concrete target to
37inspect.
38
39---
40
41## Quick-start: 5-step diagnostic flow
42
43Work through these steps in order. Most issues resolve by step 3.
44
45### Step 1: Inspect the resolved task configuration
46
47The first thing to check is whether the task is configured the way the user expects. moon merges
48configuration from multiple sources (global tasks, project config, inheritance), so the resolved
49result can surprise people.
50
51```bash
52# Show the fully resolved task config (with inheritance applied)
53moon task <project>:<task>
54
55# Machine-readable version for programmatic inspection
56moon task <project>:<task> --json
57```
58
59**What to verify:**
60
61- `command` vs `script` — if the command contains pipes (`|`), redirects (`>`), chained commands
62 (`&&`), or complex syntax, it must use `script`, not `command`.
63- `inputs` — are they too broad (`**/*` captures everything) or too narrow (missing source files)?
64 Check `state.defaultInputs` (true = using default `**/*`) and `state.emptyInputs` (true =
65 explicitly set to `[]`). Both keys are omitted from the JSON entirely when false, as is
66 `state.setRunInCi`.
67- `outputs` — are they declared for build tasks? Missing outputs means the cache can never hydrate
68 artifacts. In v2.3+, outputs also affect the **default `cacheStrategy`** of any task that depends
69 on this one (see Step 4).
70- `toolchains` — is the correct toolchain(s) assigned? An incorrect toolchain means wrong tool
71 versions.
72- `deps` — are task dependencies correct and complete? In v2.3+, each dep entry can carry a
73 `cacheStrategy` (`hash` / `ignored` / `outputs`) that controls whether the dep contributes to this
74 task's cache hash. If omitted, the default depends on whether the dep declares outputs.
75- `options` — check `persistent`, `runInCI`, `cache`, `affectedFiles`, `mutex`, `timeout`,
76 `retryCount`, `allowFailure`, and `os`.
77- `env` — in v2.5+, environment variables can also be inherited from a **workspace-level `env`** in
78 `.moon/tasks/**/*` (merged into the project's `env`, project wins), and the project can change the
79 merge behavior via `workspace.mergeStrategies.env`. A variable with a surprising value may come
80 from a layer outside the task.
81- `checks` <sup>v2.4+</sup> — shell scripts that run **before** the task. Their type determines the
82 outcome: a `requirement` failing makes the task **fail**, all `condition` checks passing makes the
83 task **skip**, and a `fingerprint` folds script output into the task hash. A surprising fail,
84 skip, or cache invalidation often traces back to a check.
85- `tags` <sup>v2.3+</sup> — labels for grouping tasks. Affects targets like `:#quality` and MQL
86 `taskTag` queries. If a task isn't matched by a `#tag` target you expected, check this list.
87- `type` — `build` (has outputs), `test` (default), or `run` (persistent)
88- `preset` — `server` or `utility` apply multiple option defaults at once.
89
90**Red flags:**
91
92- `command: 'eslint . && prettier --check .'` — shell syntax in `command` is a parse error in v2.
93 Use `script` instead.
94- Empty `outputs` on a build task — cache will never restore artifacts.
95- `inputs: ['**/*']` — too broad, cache invalidates on every change.
96- A `persistent` task in a `deps` chain — moon produces a hard error at runtime.
97- `command: 'noop'` or `nop` / `no-op` — the task is intentionally a no-op and does nothing. moon
98 treats these specially.
99- `runInCI: 'only'` — task runs in CI but NOT locally (common surprise).
100- `runInCI: 'skip'` — task is skipped in CI but relationships remain valid.
101- `os` set to a platform the user isn't on — the task is rewritten to a passing no-op at build time
102 (`moon task --json` shows `command: noop` with cleared args/outputs).
103- `allowFailure: true` — the failure is still recorded and displayed, but the pipeline continues and
104 moon exits successfully, so it's easy to miss.
105- A `condition` check present <sup>v2.4+</sup> — the task will **skip** whenever all conditions
106 pass. A task that "never runs" may have a condition that always passes.
107- A `fingerprint` check present <sup>v2.4+</sup> — its script output is hashed, so volatile output
108 (timestamps, versions) causes cache misses on every run.
109
110### Step 2: Run with maximum verbosity
111
112If the config looks right, run the task with debug logging to see what moon is actually doing under
113the hood.
114
115```bash
116# Debug-level logging with cache bypass
117moon run <project>:<task> --log debug --force
118
119# Deep debugging: reveal env vars and stdin passed to the process
120MOON_DEBUG_PROCESS_ENV=true MOON_DEBUG_PROCESS_INPUT=true moon run <project>:<task> --log trace --force
121```
122
123**What to look for in the logs:**
124
125- Toolchain resolution — is the right version of node/deno/bun/etc being used?
126- Hash generation — what sources are being hashed?
127- Affected status — is the task being skipped because it's "not affected"?
128- Process execution — what command is actually being spawned?
129
130**Visualize the execution graph** to spot dependency issues:
131
132```bash
133moon action-graph <project>:<task>
134moon action-graph <project>:<task> --dot # DOT format (useful for agents)
135```
136
137> For all graph commands and output formats, see `references/environment-debug.md`.
138
139### Step 3: Inspect cache state
140
141If the task runs but produces wrong results, or runs when it shouldn't, or doesn't run when it
142should, the cache is the likely culprit.
143
144```bash
145# Inspect a hash manifest to see what inputs were hashed
146moon hash <hash>
147
148# Compare two hashes to see what changed between runs
149moon hash <hash1> <hash2>
150
151# Short-form hashes work too
152moon hash 0b55b234 2388552f
153```
154
155> For cache file locations, hash interpretation, and the `--force` vs `--cache off` comparison, see
156> `references/cache-issues.md`.
157
158### Step 4: Diagnose the problem type
159
160Use this table to jump to the right reference:
161
162| Symptom | Likely cause | Quick check | Reference |
163| --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------------------------------- |
164| Task doesn't exist | Inheritance not applied — check `inheritedBy` conditions in `.moon/tasks/**/*` against project's `toolchains`, `stack`, `layer`, `tags` via `moon project <name> --json` | `moon task <target> --json` | `references/config-mistakes.md` |
165| "Nothing to do" | `--affected` + no changes, `runInCI: false`, or `inheritedBy` mismatch (global task not inherited) | Check flags, `options.runInCI`, and `inheritedBy` | `references/decision-tree.md` |
166| `--affected` misses changed files <sup>v2.4+</sup> | Shallow git clone in CI — merge base can't be resolved, so diffs are inaccurate (moon now logs a warning) | Check clone depth; use full history or `--filter=blob:none` | `references/decision-tree.md` |
167| Task fails: "requirement check failed" <sup>v2.4+</sup> | A `requirement` check script exited non-zero, so the task refuses to run | `moon task <target> --json` — inspect `checks` | `references/config-mistakes.md` |
168| Task skipped, not affected/CI-related <sup>v2.4+</sup> | All `condition` checks passed, so the task was intentionally skipped | `moon run <target> --log debug` — look for "conditional checks have passed" | `references/config-mistakes.md` |
169| Task errors on execution | Wrong `command`/`script`, bad toolchain | `moon run <target> --log debug` | `references/config-mistakes.md` |
170| Stale cache (cached when it shouldn't be) | Inputs too narrow, missing `env` vars, or dep `cacheStrategy: 'ignored'` (the v2.3 default for output-less deps) | `moon hash <hash>` | `references/cache-issues.md` |
171| Cache miss (re-runs every time) | Inputs too broad, volatile outputs, or dep `cacheStrategy: 'hash'` propagating upstream churn | `moon hash <h1> <h2>` | `references/cache-issues.md` |
172| Cache miss from a `fingerprint` check <sup>v2.4+</sup> | A `fingerprint` check's script output is volatile (timestamps, PIDs), changing the hash every run | `moon hash <h1> <h2>` — look for the check hash | `references/cache-issues.md` |
173| Outputs not restored after cache hit | `outputs` misconfigured; or <sup>v2.5+</sup> a daemon-side archive/hydrate failure — swallowed by the main process, logged only by the daemon (a failed hydrate becomes a silent cache miss) | Check `.moon/cache/outputs/`; `moon daemon logs` | `references/cache-issues.md` |
174| Env var has unexpected value <sup>v2.5+</sup> | Workspace-level `env` in `.moon/tasks/**/*` merged in, or `workspace.mergeStrategies.env` changed the merge behavior | `moon task <target> --json` — inspect `env` | `references/config-mistakes.md` |
175| Cache behaves differently across git worktrees <sup>v2.5+</sup> | `cache.unstable_sharedWorktreeCache` shares blobs/manifests via the base checkout's `.moon/cache` | Check the setting and `MOON_CACHE_SHARED_WORKTREE_CACHE` | `references/cache-issues.md` |
176| New dependency cycle error after upgrading to v2.5 | Async graph building (now default) validates cycles strictly, per dependency-scope partition | Set `experiments.asyncGraphBuilding: false` to confirm | `references/decision-tree.md` |
177| Build re-runs on every upstream input change <sup>v2.3+</sup> | Dep using default `cacheStrategy: 'hash'` instead of `'outputs'` | `moon task <target> --json` — inspect dep entries | `references/cache-issues.md` |
178| Task not matched by `#tag` target <sup>v2.3+</sup> | Missing `tags` on the task, or `mergeTags` dropped them during inheritance | `moon task <target> --json` — check `tags` | `references/config-mistakes.md` |
179| Task hangs / pipeline stuck | Persistent task in `deps` chain (hard error in v2) | `moon action-graph <target>` | `references/config-mistakes.md` |
180| Task is slow | Dep chain bottleneck, no parallelism | `moon action-graph <target>` | `references/decision-tree.md` |
181| Task does nothing (no-op) | Command is `noop`/`nop`/`no-op` | `moon task <target> --json` | `references/config-mistakes.md` |
182| Task fails silently | `allowFailure: true` hiding errors | Check `options.allowFailure` | `references/config-mistakes.md` |
183| Task skipped locally | `runInCI: 'only'` set | Check `options.runInCI` | `references/config-mistakes.md` |
184| Task skipped in CI | `runInCI: false` or `'skip'` | Check `options.runInCI` | `references/config-mistakes.md` |
185| Mutex contention / deadlock | Two tasks share same `mutex` | Check `options.mutex` | `references/config-mistakes.md` |
186| Task times out | `timeout` option set too low | Check `options.timeout` | `references/config-mistakes.md` |
187
188### Step 5: Validate the fix
189
190After making changes, verify the fix actually worked:
191
192```bash
193# Bypass cache to force a fresh run
194moon run <project>:<task> --force
195
196# Disable cache entirely (no reads OR writes)
197moon run <project>:<task> --cache off
198
199# Verify the resolved config reflects your changes
200moon task <project>:<task> --json
201```
202
203**`--force` vs `--cache off`:**
204
205- `--force` ignores existing cache but **writes** new cache after execution.
206- `--cache off` disables caching entirely — no reads, no writes.
207
208> For all cache modes, see `references/cache-issues.md`.
209
210---
211
212## Common mistakes at a glance
213
214These are the issues that come up most often. For details and fixes, see
215`references/config-mistakes.md`.
216
217- **Shell syntax in `command`** — pipes, `&&`, redirects require `script`; v2 rejects these as parse
218 errors.
219- **Missing `outputs` on build tasks** — cache can never hydrate artifacts.
220- **Overly broad `inputs`** — `**/*` invalidates cache on every change; be specific.
221- **Volatile outputs** — timestamps or absolute paths in build artifacts cause permanent cache
222 misses.
223- **Persistent task in `deps`** — hard error; tasks named `dev`/`start`/`serve` auto-get `server`
224 preset.
225- **`--affected` vs `--force` confusion** — `--affected` restricts; `--force` bypasses cache
226 (they're opposites).
227- **`allowFailure: true` hiding errors** — the failure is still recorded and displayed, but the
228 pipeline continues and moon exits successfully; check stderr at
229 `.moon/cache/states/<project>/<task>/stderr.log`.
230- **`mutex` contention** — shared mutex serializes tasks; combined with deps can deadlock.
231- **`runInCI: 'only'`** — task silently skips when run locally (most surprising variant).
232- **Missing outputs flip dep `cacheStrategy`** <sup>v2.3+</sup> — a dep without `outputs` now
233 defaults to `cacheStrategy: 'ignored'`. Downstream tasks stop invalidating on its changes; set
234 `cacheStrategy: 'hash'` explicitly to restore the pre-v2.3 default.
235- **MQL tag fields on task queries are version-dependent** — in v2.3–v2.4, `taskTag=` and `tag=`
236 (alias of `projectTag`) in `moon query tasks --query` silently matched _nothing_ (this also broke
237 task tag glob targets like `:#tag-*`). Fixed in v2.5: `taskTag` matches the task's own tags, and
238 `projectTag`/`tag` match the parent project's tags. On older versions, filter task tags with the
239 `--tags` flag instead (`moon query tasks --tags quality`).
240- **A `checks` script silently changes task behavior** <sup>v2.4+</sup> — a `requirement` failing
241 aborts the task, a passing `condition` skips it, and a `fingerprint` mixes script output into the
242 hash. Inspect `checks` in `moon task <target> --json` when a task fails, skips, or re-runs for no
243 obvious reason.
244- **Shallow git clone breaks `--affected`** <sup>v2.4+</sup> — a shallow clone (depth 1) prevents
245 moon from resolving the merge base, so affected detection is inaccurate or empty. Use a full
246 clone, or a blobless partial clone (`git clone --filter=blob:none`).
247- **Experiments are now on by default** <sup>v2.5+</sup> — `asyncGraphBuilding`,
248 `asyncAffectedTracking`, and `nativeFileHashing` default to enabled. When bisecting graph,
249 affected, or hashing oddities, disable the relevant experiment (config or
250 `MOON_EXPERIMENT_*=false`) and compare — but also check the user's shell/CI for
251 `MOON_EXPERIMENT_*` or `MOON_CACHE_*` overrides that silently change behavior.
252- **Daemon archiving/hydration failures are invisible in the main process** <sup>v2.5+</sup> — with
253 the daemon enabled, task outputs are archived and hydrated in the background, and failures only
254 appear in `moon daemon logs`. To rule the daemon out, re-run with `MOON_DAEMON=false`.
255- **Workspace-level `env` is a new inheritance layer** <sup>v2.5+</sup> — `.moon/tasks/**/*` files
256 can define `env` inherited by all matching projects. Project values win on conflict, unless
257 `workspace.mergeStrategies.env` says otherwise (`append`, `prepend`, `preserve`, `replace`).
258
259---
260
261## When to load references
262
263Each reference file covers a specific problem domain in depth. Load them only when the diagnostic
264flow points you there — don't load everything upfront.
265
266| Reference | When to load |
267| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
268| `references/decision-tree.md` | When the symptom doesn't match the quick table above, or you need a systematic walk-through of all possibilities. |
269| `references/cache-issues.md` | When the problem is clearly cache-related: unexpected hits, unexpected misses, outputs not restoring. |
270| `references/config-mistakes.md` | When the task config is wrong: command vs script, inheritance bugs, presets, persistent tasks, affectedFiles, mutex, timeout, retries, runInCI variants, allowFailure, os. |
271| `references/environment-debug.md` | When you need to go deeper with env vars, log levels, trace profiles, or inspection tools. |