jdx/mise · error

oci mount_point must not be empty

Error message

oci mount_point must not be empty

What it means

During `mise oci build`, the in-image install path (mount point) is resolved from build opts, then mise.toml `[oci] mount_point`, then the `oci.default_mount_point` setting (default `/mise`), and trailing '/' characters are trimmed. If the trimmed result is empty — classically `mount_point = "/"` — the build refuses to continue because tools cannot be mounted at an empty path. The image's MISE_DATA_DIR is set from this value, so emptiness is fatal.

Source

Thrown at src/oci/builder.rs:178

    pub async fn build(self) -> Result<BuildOutput> {
        let versions = self.ts.list_current_versions();
        if versions.is_empty() {
            warn!("mise oci build: no tools in the toolset — image will have only the base layer");
        }
        reject_unsupported_backends(&versions)?;

        file::create_dir_all(&self.opts.out_dir)?;
        let layout = ImageLayout::init(&self.opts.out_dir)?;

        let mount_point = self
            .opts
            .mount_point
            .clone()
            .or_else(|| self.oci.mount_point.clone())
            .unwrap_or_else(|| Settings::get().oci.default_mount_point.clone());
        let mount_point = mount_point.trim_end_matches('/').to_string();
        if mount_point.is_empty() {
            bail!("oci mount_point must not be empty");
        }
        if !mount_point.starts_with('/') {
            bail!(
                "oci mount_point must be an absolute path (got {mount_point:?}); \
                 a relative value makes MISE_DATA_DIR inside the container \
                 depend on the working directory and mis-resolve tools."
            );
        }

        let owner = resolve_layer_owner(self.opts.owner, &self.oci);
        let copies: Vec<&OciCopy> = self.oci.copy.iter().chain(&self.opts.copy).collect();

        // --- 1. Base image (optional) ---
        let from_ref = self
            .opts
            .from
            .clone()
            .or_else(|| self.oci.from.clone())

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Set a real directory such as `mount_point = "/mise"` or `"/opt/mise"` in `[oci]` of mise.toml (or the build options)
  2. If overriding the default globally, set `oci.default_mount_point` (env MISE_OCI_DEFAULT_MOUNT_POINT) to a non-root absolute path
  3. Remove the override entirely to fall back to the default `/mise`

Example fix

# before (mise.toml)
[oci]
mount_point = "/"

# after (mise.toml)
[oci]
mount_point = "/mise"
Defensive patterns

Strategy: validation

Validate before calling

python3 - <<'EOF'
import tomllib, sys
cfg = tomllib.load(open('mise.toml', 'rb'))
mp = cfg.get('oci', {}).get('mount_point', '/mise').rstrip('/')
if not mp: sys.exit('mount_point trims to empty — set e.g. "/mise"')
print('mount_point OK:', mp)
EOF

Prevention

When it happens

Trigger: Setting `mount_point = "/"` (or `//`) in `[oci]` of mise.toml or in build opts; or configuring `oci.default_mount_point` to `/`, which trims to empty. Both `mise oci build` invocations and programmatic builder use hit the check before any layer work starts.

Common situations: Attempting to install tools at the image root '/' for a minimal container; copy-pasted configs; intentionally-absolute-but-degenerate values like `"/"`.

Understand the failure class

Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.

Related errors


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