jdx/mise · error

invalid dependency graph digest

Error message

invalid dependency graph digest

What it means

When parsing a dependency-graph pointer from the lockfile, the `digest` must be a `sha256:`-prefixed, exactly-64-hex-character value. `GraphRef::parse` bails otherwise, because the digest is used to detect tampering/unexpected changes in the sidecar dependency graph.

Solutions

  1. Set the digest to the correct `sha256:<64 hex chars>` of the sidecar dependency graph file
  2. Regenerate the lockfile so the digest is recomputed automatically
  3. Remove any hand edits and re-lock from a clean state
  4. Verify with `sha256sum` that the recorded digest matches the sidecar file

Example fix

# before
digest = "e3b0c442"
# after
digest = "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
Defensive patterns

Strategy: validation

Validate before calling

fn valid_sha256_digest(d: &str) -> bool {
    d.strip_prefix("sha256:")
        .is_some_and(|s| s.len() == 64 && s.bytes().all(|b| b.is_ascii_hexdigit()))
}

Type guard

fn is_sha256_digest(s: &str) -> bool {
    s.strip_prefix("sha256:")
        .is_some_and(|h| h.len() == 64 && h.bytes().all(|b| b.is_ascii_hexdigit()))
}

Prevention

When it happens

Trigger: Loading a lockfile whose dependency entry has a missing, empty, non-sha256, or wrong-length digest — e.g. `digest = "abc123"`, `digest = "sha256:xyz"`, or a digest computed with a different algorithm pasted in.

Common situations: Hand-edited lockfiles; digests generated by other tooling (sha512, md5); truncated digests from copy/paste; older lockfile formats without proper digests.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/075487260ff03ec3. Report an issue: GitHub.

Appendix: source

Thrown at src/lockfile/graph.rs:158

            *dir = absolute(lockfile.parent().unwrap_or(Path::new("."))).join(&*dir);
        }
        Ok(())
    }
    pub(crate) fn parse(value: toml::Value) -> Result<Self> {
        if value.get("path").is_some() {
            #[derive(Deserialize)]
            #[serde(deny_unknown_fields)]
            struct Pointer {
                path: PathBuf,
                digest: String,
            }
            let p: Pointer = value.try_into()?;
            if !p
                .digest
                .strip_prefix("sha256:")
                .is_some_and(|s| s.len() == 64 && s.bytes().all(|b| b.is_ascii_hexdigit()))
            {
                bail!("invalid dependency graph digest");
            }
            Ok(Self::Sidecar {
                dir: p.path,
                digest: p.digest,
                cell: OnceLock::new(),
            })
        } else {
            debug!(
                "migrating inline dependency graph to a native sidecar on the next lockfile save"
            );
            Ok(Self::from(value.try_into::<T>()?))
        }
    }
    pub(crate) fn pointer(&self, base: &Path) -> Result<toml::Value> {
        let dir = self
            .dir()
            .ok_or_else(|| eyre!("dependency sidecar has not been prepared"))?;
        let relative = dir.strip_prefix(absolute(base))?;

View on GitHub (pinned to 533346cc37)