jdx/mise · error

push destination must be a fully-qualified reference (e.g. `

Error message

push destination must be a fully-qualified reference (e.g. `ghcr.io/you/devenv:tag`); got {:?}

What it means

`mise oci push` requires the destination to be a fully-qualified OCI reference: registry host + repository path + optional tag/digest (e.g. `ghcr.io/you/devenv:tag`). Unlike docker/podman, mise has no implicit default registry (docker.io) to expand short names to, so it does an up-front `contains('/')` check and bails before building or uploading anything. The `{:?}` in the message is the raw reference string you passed.

Source

Thrown at src/cli/oci/push.rs:94

    #[clap(long, value_name = "UID[:GID]")]
    owner: Option<LayerOwner>,

    /// Maintain the tag as a multi-arch image index
    ///
    /// Pushes this build's manifest by digest and points the tag at an OCI
    /// image index containing one entry per platform, preserving entries
    /// other architectures pushed. Run `mise oci push --update-index` from
    /// one runner per platform to assemble a multi-arch tag.
    #[clap(long)]
    update_index: bool,
}

impl Push {
    pub async fn run(self) -> Result<()> {
        Settings::get().ensure_experimental("mise oci push")?;

        if !self.reference.contains('/') {
            bail!(
                "push destination must be a fully-qualified reference \
                 (e.g. `ghcr.io/you/devenv:tag`); got {:?}",
                self.reference
            );
        }
        // Keep the temp dir alive for the duration of the push — it removes
        // itself on drop, so multi-hundred-megabyte image layouts don't
        // accumulate in /tmp.
        let mut reused_layers = 0;
        let (image_dir, _tempdir_guard): (PathBuf, Option<TempDir>) =
            if let Some(d) = &self.image_dir {
                if !d.join("index.json").is_file() {
                    bail!(
                        "{}: does not look like an OCI image layout (missing index.json)",
                        d.display()
                    );
                }
                (d.clone(), None)

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Use a fully-qualified reference with registry host and namespace: `mise oci push ghcr.io/<you>/devenv:tag`
  2. For a local registry include the port: `mise oci push localhost:5000/devenv:tag`
  3. Check the variable your script feeds to push actually contains `registry/namespace/repo`

Example fix

# before
mise oci push devenv:1.0
# after
mise oci push ghcr.io/you/devenv:1.0
Defensive patterns

Strategy: validation

Validate before calling

# bash: require a slash before invoking push
ref="${1:?reference required}"
if [[ "$ref" != *"/"* ]]; then
  echo "ref must be registry/namespace/repo[:tag]" >&2
  exit 2
fi
mise oci push "$ref"

Prevention

When it happens

Trigger: Running `mise oci push devenv:tag`, `mise oci push myimage`, or `mise oci push latest` — any destination string without at least one slash. Also scripts that assemble the reference from a short variable or a name without namespace.

Common situations: Muscle memory from `docker push name:tag` where the daemon silently injects docker.io; copying a repo short name from a browser URL (e.g. just `devenv`); CI variables that hold only the image name without registry/namespace.

Related errors


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