jdx/mise · error

dpkg-query failed: {}

Error message

dpkg-query failed: {}

What it means

mise's Debian/Ubuntu (apt) backend shells out to `dpkg-query` to classify requested packages as installed or missing. Exit code 1 is expected and tolerated (it just means some packages are unknown to dpkg, so they are reported Missing); this error fires for any other nonzero exit — dpkg-query failed structurally (locked or malformed database, missing binary, permission problem) and the result is unusable.

Source

Thrown at src/system/packages/apt.rs:141

        if pkgs.is_empty() {
            return Ok(vec![]);
        }
        let mut args = vec![
            "-W".to_string(),
            "-f=${Package}\\t${db:Status-Status}\\t${Version}\\t${Architecture}\\n".to_string(),
        ];
        args.extend(pkgs.iter().map(|p| dpkg_name(&p.name).to_string()));
        debug!("$ dpkg-query {}", args.join(" "));
        let output = tokio::process::Command::new("dpkg-query")
            .args(&args)
            .stdin(Stdio::null())
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .output()
            .await?;
        // exit 1 just means some packages are unknown to dpkg — they're Missing
        if !output.status.success() && output.status.code() != Some(1) {
            bail!(
                "dpkg-query failed: {}",
                String::from_utf8_lossy(&output.stderr).trim()
            );
        }
        let stdout = String::from_utf8_lossy(&output.stdout);
        Ok(parse_dpkg_query(&stdout, pkgs))
    }

    async fn install(&self, pkgs: &[PackageRequest], opts: &InstallOpts) -> Result<()> {
        if opts.update || self.lists_missing() {
            self.update(opts)?;
        }
        // `--` keeps package operands from ever being parsed as apt-get
        // options; pins render to apt's native name=version syntax and
        // name:arch qualifiers pass through in the name
        let mut args = vec!["install".to_string(), "-y".to_string(), "--".to_string()];
        args.extend(pkgs.iter().map(|p| match &p.version {
            Some(v) => format!("{}={v}", p.name),

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Run the same query manually: `dpkg-query -W <package>` and read the stderr shown in the message
  2. Clear dpkg's dirty state: `sudo dpkg --configure -a` then `sudo apt-get -f install`
  3. Check for concurrent apt/dpkg processes holding locks (`ps aux | grep -E 'apt|dpkg'`) and let them finish
  4. In stripped images without a working dpkg, don't declare apt packages in mise; install them via the Dockerfile
Defensive patterns

Strategy: retry

Validate before calling

async fn dpkg_query_ok() -> bool {
    tokio::process::Command::new("dpkg-query")
        .args(["-W", "dpkg"])
        .stdin(std::process::Stdio::null())
        .stdout(std::process::Stdio::null())
        .stderr(std::process::Stdio::piped())
        .output()
        .await
        .map(|o| o.status.success() || o.status.code() == Some(1))
        .unwrap_or(false)
}

Try / catch

Catch errors matching "dpkg-query failed" and retry after a short backoff (dpkg lock contention is transient); if it persists, direct the user to run `dpkg --configure -a` rather than treating packages as installed or missing.

Prevention

When it happens

Trigger: Running mise package operations on Debian/Ubuntu when `dpkg-query` exits with a code other than 0 or 1: another apt/dpkg process holds /var/lib/dpkg locks mid-run, /var/lib/dpkg/status is corrupted, or dpkg is absent/broken in a hand-rolled minimal container.

Common situations: CI base images where `dpkg --configure -a` was never run; apt interrupted by a killed pipeline leaving dpkg dirty; concurrent `apt-get install` during mise bootstrap; containers where /var/lib/dpkg was partially removed.

Related errors


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