jdx/mise · error

apt-cache policy failed

Error message

apt-cache policy failed: {}

What it means

The apt backend shells out to `apt-cache policy` to decide whether a package is installable. apt-cache reports unknown package names on stderr without failing, so a nonzero exit status means apt-cache itself failed to run, and mise raises the trimmed stderr.

Solutions

  1. Read the stderr embedded in the message
  2. Run `apt-get update` to (re)build package lists
  3. Verify manually: apt-cache policy <package>
  4. If the host is not Debian-based, remove apt from mise's bootstrap package managers

Example fix

// before
# container missing lists
apt-cache policy curl  # exits nonzero
// after
RUN apt-get update && mise install
Defensive patterns

Strategy: try-catch

Validate before calling

apt-cache policy >/dev/null 2>&1 || (apt-get update && apt-cache policy >/dev/null) || echo 'apt-cache unusable'

Try / catch

if let Err(e) = available(pkg) {
    if e.to_string().contains("apt-cache policy failed") {
        run("apt-get update");
        retry(pkg)?;
    }
}

Prevention

When it happens

Trigger: `apt-cache policy` exits nonzero — e.g. apt package lists are corrupt, /var/lib/apt is broken, or apt-cache is missing/unusable on the host.

Common situations: Broken or never-initialized apt lists (no `apt-get update` ever run) in containers; corrupted /var/lib/apt/lists in a slim Docker image; running where apt exists but its cache directory is unreadable.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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

Appendix: source

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

    /// holding an arch-qualified name must query it alone.
    async fn policy_installable(&self, args: &[&str]) -> Result<std::collections::HashSet<String>> {
        debug!("$ apt-cache policy {}", args.join(" "));
        let output = tokio::process::Command::new("apt-cache")
            .arg("policy")
            .args(args)
            // apt translates the stanza labels this parses, so pin the locale
            // rather than reading "Kandidat:" as an unavailable package
            .env("LC_ALL", "C")
            .env("LANGUAGE", "C")
            .stdin(Stdio::null())
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .output()
            .await?;
        // unknown names are reported on stderr and do not fail the command,
        // so a nonzero status means apt-cache itself could not run
        if !output.status.success() {
            bail!(
                "apt-cache policy failed: {}",
                String::from_utf8_lossy(&output.stderr).trim()
            );
        }
        Ok(parse_apt_cache_policy(&String::from_utf8_lossy(
            &output.stdout,
        )))
    }

    fn update(&self, opts: &InstallOpts) -> Result<()> {
        let args = vec!["update".to_string()];
        if opts.dry_run {
            miseprintln!(
                "{}",
                sudo::argv_with_env("apt-get", &args, &debian_frontend()).join(" ")
            );
            return Ok(());
        }

View on GitHub (pinned to 533346cc37)