jdx/mise · error
{} package hook did not return state for '{}'
Error message
{} package hook did not return state for '{}' What it means
After running the plugin's package hook, installed() looks up state for the requested package. If the hook's response contains no entry for that package, mise fails explicitly, because it cannot determine whether the package is installed, missing, or mismatched — information needed by install, upgrade, and prune planning.
Source
Thrown at src/system/packages/plugin.rs:569
let returned = by_name.get(&request.name);
let state = match returned {
Some(pkg) if pkg.state == "installed" => {
let installed = pkg.version.clone().unwrap_or_default();
match &request.version {
Some(requested) if requested != &installed => {
PackageState::VersionMismatch { installed }
}
_ => PackageState::Installed { version: installed },
}
}
Some(pkg) if pkg.state == "missing" => PackageState::Missing,
Some(pkg) => bail!(
"{} package hook returned invalid state '{}' for '{}'",
self.name,
pkg.state,
request.name
),
None => bail!(
"{} package hook did not return state for '{}'",
self.name,
request.name
),
};
Ok(PackageStatus {
request: request.clone(),
state,
})
})
.collect()
}
async fn install(&self, pkgs: &[PackageRequest], opts: &InstallOpts) -> Result<()> {
if opts.dry_run {
return self.action(pkgs, opts, false).await;
}
let _lock = self.operation_lock()?;View on GitHub (pinned to afd2eddd3a)
Solutions
- Fix the plugin's status hook so it always returns an entry for every queried package, matching request names exactly
- Update or reinstall the plugin to a version whose hook handles the package correctly
- Run the underlying manager's own query (e.g. `brew list --versions <pkg>`) to check the package manually
- Check for name mismatches (aliases, case) between the request and what the manager reports
Example fix
// before (plugin hook returns nothing for 'redis')
-- hook only reports packages it found installed
// after (plugin hook Lua)
-- always emit an entry per requested package
return { { name = "redis", state = "missing" } } Defensive patterns
Strategy: validation
Validate before calling
let resp = run_hook(&req.name)?;
if !resp.iter().any(|p| p.name == req.name) {
/* hook incomplete: treat as missing or fix plugin */
} Type guard
fn hook_answered(pkgs: &[HookPkg], name: &str) -> bool {
pkgs.iter().any(|p| p.name == name)
} Try / catch
match plugin.installed(&req).await {
Err(e) if e.to_string().contains("did not return state") => {
Ok(PackageStatus { state: PackageState::Missing, ..Default::default() })
}
other => other,
} Prevention
- Ensure plugin status hooks emit an entry for every requested package, including missing ones
- Match package names exactly (beware aliases and case differences between manager output and requests)
- Test the hook with both installed and not-installed packages
When it happens
Trigger: The package hook (called from installed via prune_plan, apply_prune_plan, install, or upgrade) returns a list/record that omits the requested package name — e.g. the Lua hook filters it out, matches names case-sensitively, or returns an empty/partial result.
Common situations: Plugin hook bug where the queried package name doesn't match the manager's reported name (alias vs real name); hook returns early on error and omits entries; package was uninstalled between listing and check.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- {} package hook returned invalid state '{}' for '{}'
- brew-cask: unresolved recovery for {} still preserves its or
- brew-cask: unresolved recovery for newly created target {}
- pre_use hook is not implemented
- {tool}'s bin/install exited successfully but installed nothi
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/2376668f84895473.
Report an issue: GitHub.