debug-task

Diagnose and fix moon tasks that are broken, misconfigured, or behaving unexpectedly. Use this skill when a moon task is failing, not running, skipped, hanging, producing stale or wrong output, cached when it shouldn't be, re-running every time when it should be cached, or when outputs are empty or

By moonrepo · 384 installs

npx skills add moonrepo/moon --skill debug-task

Source repository · Upstream listing

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](https://moonrepo.dev/docs). 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. 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 [] , or a task of the root level project in a monorepo that configured no inputs). 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. <sup v2.6+</sup The order is significant: configured toolchains come first, followed by related ones (those they require, and enabled toolchains that require them, like npm for node ), and the first is the primary (used by $taskToolchain , and wins when toolchain environments are activated and paths are prepended to PATH ). 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. In v2.6+, each dep also has a type : required (default, runs before and must pass), cleanup (runs after the task, even when it fails), or wait (the task only waits for it to start ). The human readable moon task output labels the non required ones, like db:stop (cleanup) . options — check persistent , runInCI , cache , affectedFiles , mutex , timeout , retryCount , allowFailure , expectFailure , envOverride , 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. In v2.6+, toolchains that have been setup can also activate their environment (like JAVA HOME ), which sets variables the task config never mentions — but never overrides variables the task already configures. Also note that a task's env value only applies when the variable isn't already set in the shell — an exported shell value wins at runtime. checks <sup v2.4+</sup — 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 <sup v2.3+</sup — 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 — an explicit type wins; otherwise build (has outputs), run (has a preset , or is persistent), else test . A persistent task with outputs is build . preset — server or utility apply multiple option defaults at once. Red flags: command: 'eslint . && prettier check .' — shell syntax in command is a task build error in v2 ( task builder::unsupported command syntax ). Use script instead. Empty outputs on a build task — cache will never restore artifacts. inputs: [' / '] — too broad, cache invalidates on every change. A non persistent task with a required dep on a persistent task — a hard error when tasks are built. In v2.6+, use type: 'wait' to only wait for it to start — and since wait deps are still subject to the runInCI check (persistent and server preset tasks default to runInCI: false ), also set runInCI: true on the persistent dep (or 'skip' on it, or false on the dependent), otherwise it fails with run in ci mismatch . A wait dep <sup v2.6+</sup with no cleanup dep that stops it — a waited on task is never stopped for you, so a non persistent one keeps the pipeline running until it exits, and a persistent one keeps it running until moon is exited. A wait dep on a task that has caching enabled <sup v2.6+</sup — waited on deps are started before the cache is checked, so on a cache hit the server starts and is then immediately stopped by its cleanup. Disable cache on tasks that wait on long running deps. 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. expectFailure: true <sup v2.6+</sup — the task passes when its command fails, and fails with "was expected to fail, but it passed" once the underlying problem is fixed (remove the setting). It's never cached, and exit codes 126/127 or a signal don't count as the expected failure. A condition check present <sup v2.4+</sup — the task will skip whenever all conditions pass. A task that "never runs" may have a condition that always passes. A fingerprint check present <sup v2.4+</sup — 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. 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"? force runs tasks even when they're not affected, so drop it (and pass affected ) when diagnosing this. Process execution — what command is actually being spawned? Visualize the execution graph to spot dependency issues: Always pass dot or json as an agent. Without them, the command starts a local web server and opens a browser, and blocks until it's interrupted. 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. <sup v2.6+</sup Hash manifests are stored as blobs in the local content addressable cache ( .moon/cache/blobs/ ), not as .moon/cache/hashes/<hash .json files, so always read them through moon hash . If it reports "Unable to find a hash manifest", the manifest may have been garbage collected — re run the task with force to regenerate it. 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 the project's toolchains , config.language , config.stack , config.layer , config.tags via moon project <name json (a detected only language doesn't match inheritedBy.languages ) 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 (or runs everything) Shallow git clone in CI — with no base, moon warns "Detected a shallow checkout…" and disables affected (so everything runs); with an explicit base, diffs may be inaccurate Check clone depth; use full history ( fetch depth: 0 ) references/decision tree.md Task fails: "…is unable to run as the requirement check … failed" <sup v2.4+</sup A requirement check script exited non zero ( task runner::requirement check failed ); a failing fingerprint script also fails the task ( task runner::hash check failed ) moon task <target json — inspect checks references/config mistakes.md 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 "Skipping task as all conditional checks have passed" references/config mistakes.md Task errors on execution Wrong command / script , bad toolchain