jdx/mise · error
expected key file
Error message
expected key file
What it means
This is a test-only panic emitted by a Rust `let-else` destructuring assertion in src/sops.rs. `read_key_file` returns a `ResolvedAgeKey` enum, and the test asserts the variant is `ResolvedAgeKey::File` (a parsed key file containing identities); any other variant (e.g. an env-based or empty resolution) falls into the else branch and panics with 'expected key file'. It signals that the age key parser did not produce a file-backed key from the given contents.
Source
Thrown at src/sops.rs:314
#[cfg(test)]
mod tests {
use super::*;
fn read_key_file(contents: &str) -> Option<ResolvedAgeKey> {
let tmp = tempfile::tempdir().unwrap();
let path = tmp.path().join("keys.txt");
file::write(&path, contents).unwrap();
read_age_key_file(path.to_string_lossy().to_string(), &mut Ok, "test key file")
}
#[test]
fn reads_multiple_age_keys_in_order() {
let key =
read_key_file("# first key is unrelated\r\nKEY-1\r\n\r\n# matching key\r\nKEY-2\r\n")
.unwrap();
let ResolvedAgeKey::File { identities, .. } = &key else {
panic!("expected key file");
};
assert_eq!(identities, &["KEY-1", "KEY-2"]);
assert_eq!(key.env_value(true), "KEY-1,KEY-2");
assert_eq!(key.env_value(false), "KEY-1\nKEY-2");
}
#[test]
fn preserves_invalid_non_comment_lines() {
let key = read_key_file("not-an-age-key\n").unwrap();
let ResolvedAgeKey::File { identities, .. } = key else {
panic!("expected key file");
};
assert_eq!(identities, &["not-an-age-key"]);
}
#[test]
fn ignores_empty_and_comment_only_key_files() {
assert_eq!(View on GitHub (pinned to afd2eddd3a)
Solutions
- Ensure the key file content passed to `read_key_file` contains at least one non-comment identity line (e.g. a line starting with AGE-... or KEY-...).
- Inspect which `ResolvedAgeKey` variant is actually returned (add a debug print or match) and adjust the expectation or the parser accordingly.
- If the file is intentionally empty/comment-only, handle the non-File variants explicitly instead of asserting the File variant.
- Verify line-ending handling (CRLF vs LF) and comment stripping in `read_key_file` haven't regressed.
Example fix
// before
let ResolvedAgeKey::File { identities, .. } = &key else {
panic!("expected key file");
};
// after
let identities = match &key {
ResolvedAgeKey::File { identities, .. } => identities,
other => panic!("expected key file, got {other:?}"),
}; Defensive patterns
Strategy: type-guard
Validate before calling
// rust
if !content.lines().any(|l| !l.trim().is_empty() && !l.trim_start().starts_with('#')) {
return Err("key file has no identity lines");
} Type guard
fn as_key_file(key: &ResolvedAgeKey) -> Option<&Vec<String>> {
match key {
ResolvedAgeKey::File { identities, .. } => Some(identities),
_ => None,
}
} Try / catch
// rust: replace let-else panic with a Result-returning match
let identities = match &key {
ResolvedAgeKey::File { identities, .. } => identities,
other => return Err(anyhow!("expected key file, got {other:?}")),
}; Prevention
- Always include the unexpected value in panic messages for debuggability.
- Validate key file contents (non-comment lines present) before parsing.
- Add unit tests for empty and comment-only key files.
- Prefer returning Err over panicking in library code paths.
When it happens
Trigger: Calling `read_key_file` with contents that resolve to a non-`File` variant of `ResolvedAgeKey` — e.g. content that the parser treats as empty, comment-only, or otherwise not yielding identity lines — inside a context (test or code copy) that expects `ResolvedAgeKey::File`.
Common situations: Feeding a key file that contains only comments or blank lines; a parser change that reclassifies valid KEY lines; refactoring `read_key_file` so multi-line or CRLF files resolve to a different variant; pointing at an age key file that is actually a placeholder.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/3eabb42bdec668f5.
Report an issue: GitHub.