jdx/mise · error
package hook did not return state for
Error message
{} package hook did not return state for '{}' What it means
When mise asks a package plugin for a package's status, the hook is expected to return a state entry for every requested package. If the returned list contains no entry for a requested package (`None` case in the match), `installed` fails with the plugin name and package name rather than inventing a default status. This guarantees status checks are total: every request gets an explicit answer from the hook.
Solutions
- Fix the plugin's status hook to return an entry (installed or missing) for every requested package name.
- Check for name mismatches between the request and the hook's reported names (aliases, case, versioned names) and normalize them in the hook.
- Run the plugin's status hook manually with the failing package name to see why it is omitted.
- Update the plugin to a version that handles unknown/missing packages by reporting state 'missing' instead of omitting them.
Example fix
-- before: hook omits untracked packages
local results = {}
for _, p in ipairs(tracked) do table.insert(results, p) end
return results
-- after: always answer for every requested package
for _, req in ipairs(requested) do
if not find(results, req.name) then
table.insert(results, { name = req.name, state = 'missing' })
end
end
return results Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure the hook answers for every requested package before calling mise
function assertTotal(requested, returned) {
const got = new Set((returned ?? []).map((e) => e?.name));
const missing = requested.filter((r) => !got.has(r.name));
if (missing.length) throw new Error(`Hook omitted state for: ${missing.map((m) => m.name).join(', ')}`);
} Type guard
const answersAll = (requested, returned) => { const got = new Set((returned ?? []).map((e) => e?.name)); return requested.every((r) => got.has(r.name)); }; Try / catch
try { await misePkgInstall(plugin, pkgs) } catch (e) { const m = String(e).match(/hook did not return state for '(.*?)'/); if (m) { console.error(`Plugin hook omitted '${m[1]}' — normalize names or default to state 'missing'`); } else throw e; } Prevention
- Design hooks to return an entry for EVERY requested package, defaulting to state 'missing'.
- Normalize package names (case, aliases) identically in requests and hook responses.
- Test the hook with a package it does not track to confirm it still answers 'missing'.
- Log hook internals during development so dropped entries surface early.
When it happens
Trigger: Calling `installed` (via prune_plan, apply_prune_plan, install, or upgrade) where the plugin's status hook returns a list that omits the requested package entirely — e.g. the hook filters out packages it does not recognize or its query silently skips failures.
Common situations: A plugin hook that only reports packages present in its own config, while mise asks about a package added elsewhere; a Lua hook bug where an error for one package causes it to be dropped from the result; name normalization differences (case/alias) between mise's request and the hook's keys.
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
- package plugin ' ' does not support uninstall; add…
- cloned request builder should remain cloneable
- Consider enabling 'keep_danger_placeholders' option (to…
- Impossible to find at least two unused byte codes in this…
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/2376668f84895473.
Report an issue: GitHub.
Appendix: 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 533346cc37)