nikivdev/code · error

AI task '{}' has no moon workspace root; cannot build cached

Error message

AI task '{}' has no moon workspace root; cannot build cached binary

What it means

Thrown by build_task_cached in src/ai_tasks.rs when it tries to build a cached binary for an AI task but the resolved workspace directory contains neither moon.mod.json nor moon.mod. Without a moon workspace root there is nothing to build with moon.

Source

Thrown at src/ai_tasks.rs:300

    let mut cmd = moon_run_command(task, project_root, args);
    let output = cmd.output().with_context(|| {
        format!(
            "failed to run AI task {} via moon ({})",
            task.id,
            task.path.display()
        )
    })?;
    Ok(output)
}

pub fn build_task_cached(
    task: &DiscoveredAiTask,
    project_root: &Path,
    force_rebuild: bool,
) -> Result<CachedTaskArtifact> {
    let (workspace_dir, run_path) = resolve_moon_workspace_and_entry(task, project_root);
    if !workspace_dir.join("moon.mod.json").exists() && !workspace_dir.join("moon.mod").exists() {
        bail!(
            "AI task '{}' has no moon workspace root; cannot build cached binary",
            task.id
        );
    }

    let cache_key = compute_cache_key(task, &workspace_dir, &run_path)?;
    let cache_dir = ai_task_cache_root()?.join(&cache_key);
    fs::create_dir_all(&cache_dir)
        .with_context(|| format!("failed to create ai task cache dir {}", cache_dir.display()))?;
    let binary_path = cache_dir.join("task-bin");
    if binary_path.exists() && !force_rebuild {
        return Ok(CachedTaskArtifact {
            cache_key,
            binary_path,
            rebuilt: false,
        });
    }

View on GitHub (pinned to a747e741ae)

Solutions

  1. Run from (or point project_root at) the directory containing moon.mod.json
  2. Initialize the workspace with a moon.mod.json/moon.mod if this task was intended to be a moon module
  3. Skip caching and use the non-cached runner (run_task_via_moon) for non-moon tasks

Example fix

// before
let cached = build_task_cached(task, wrong_root, false)?;
// after
let cached = build_task_cached(task, project_root.join("moon-workspace"), false)?; // dir containing moon.mod.json
Defensive patterns

Strategy: validation

Validate before calling

fn is_moon_workspace(dir: &Path) -> bool {
    dir.join("moon.mod.json").exists() || dir.join("moon.mod").exists()
}
if !is_moon_workspace(project_root) { eprintln!("not a moon workspace"); }

Try / catch

if let Err(e) = build_task_cached(task, root, false) {
    if e.to_string().contains("no moon workspace root") {
        // fall back to non-cached path
        return run_task_via_moon(task, root, args);
    }
    return Err(e);
}

Prevention

When it happens

Trigger: run_task_cached or run_task_cached_output calls build_task_cached, and resolve_moon_workspace_and_entry returns a directory lacking moon.mod.json/moon.mod — e.g. the task lives outside a moon workspace or the marker file was moved/renamed.

Common situations: Running a cached AI task from a subdirectory that is not a moon module root; moon.mod.json renamed after a toolchain version change; task configured with the wrong project root.

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/62e2c3180d04542a. Report an issue: GitHub.