jdx/mise · error

mise oci: no project mise config found in the current direct

Error message

mise oci: no project mise config found in the current directory or any parent. Add a `mise.toml` to the project, or pass `--include-global` to use tools and [oci] settings from your global config (note: asdf/vfox plugins remain unsupported).

What it means

`mise oci` commands build images from your project's toolset, and by default they only trust project-level config (any mise config with a project_root, including one walked up from CWD to a monorepo root). If no such file exists, they bail rather than silently baking your personal global tools into a production image. --include-global opts in; asdf/vfox plugins stay unsupported either way.

Source

Thrown at src/cli/oci/common.rs:108

}

/// Configs at-or-below the project root.
///
/// `cf.project_root().is_some()` is the right scope: it's None for the global
/// config, the system config, and parent-dir configs that live directly under
/// $HOME (e.g. `~/mise.toml` someone uses to set their default Node). It's
/// Some for any project config, including those walked up from CWD into a
/// monorepo root — which we *do* want included (sub-project + monorepo root
/// share the toolset of the deployable).
fn project_config_files(config: &Config) -> Result<ConfigMap> {
    let project_files: ConfigMap = config
        .config_files
        .iter()
        .filter(|(_, cf)| cf.project_root().is_some())
        .map(|(p, cf)| (p.clone(), cf.clone()))
        .collect();
    if project_files.is_empty() {
        bail!(
            "mise oci: no project mise config found in the current directory or any parent. \
             Add a `mise.toml` to the project, or pass `--include-global` to use tools and \
             [oci] settings from your global config (note: asdf/vfox plugins remain \
             unsupported)."
        );
    }
    Ok(project_files)
}

async fn build_project_toolset(
    config: &std::sync::Arc<Config>,
    project_files: ConfigMap,
) -> Result<crate::toolset::Toolset> {
    // ConfigScope::LocalOnly belt-and-suspenders: the project-files filter
    // already drops global/system, but LocalOnly *also* drops MISE_*_VERSION
    // ad-hoc overrides from the environment, which shouldn't bake into an
    // image either.
    ToolsetBuilder::new()

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Add a mise.toml to the project root declaring the tools the image needs
  2. Or explicitly opt in to global config: run the oci command with `--include-global`
  3. If tools come from asdf/vfox plugins, migrate those tools to a mise-supported backend first — oci will not install plugin-based tools

Example fix

# before
cd /src/app && mise oci build
# after — create mise.toml first
printf '[tools]\nnode = "22"\n' > /src/app/mise.toml
mise oci build
Defensive patterns

Strategy: validation

Validate before calling

#!/usr/bin/env bash
found=0
for f in mise.toml mise.local.toml .mise.toml; do
  d=$(pwd); while [[ "$d" != / ]]; do [[ -f "$d/$f" ]] && { found=1; break 2; }; d=$(dirname "$d"); done
done
[[ $found -eq 1 ]] || MISE_INCLUDE_GLOBAL=1  # or add a mise.toml before running oci
mise oci build

Try / catch

mise oci build 2>err.log || { grep -q 'no project mise config found' err.log && { printf '[tools]\nnode = "22"\n' > mise.toml; mise oci build; }; }

Prevention

When it happens

Trigger: Running `mise oci build` (or related oci subcommands) in a directory tree with no mise.toml/mise.local.toml/.tool-versions-with-project-root; running from a subfolder of a non-mise project; containers where only the global config exists.

Common situations: First `mise oci` use in a repo not yet using mise; building images from a fresh clone where mise.toml lives in a different repo; wanting global defaults in images without realizing the security implication.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/da6f8fbb4ac167ec. Report an issue: GitHub.