Repository navigation
[rust] Selenium Manager panics instead of degrading when the metadata cache cannot be read #18088
Description
💬 Description
Selenium Manager treats an unusable se-metadata.json cache inconsistently: some failures degrade gracefully, one aborts the process. This came up reviewing #18087, which improves the diagnostic for the fatal arm but deliberately leaves the behaviour as-is.
se-metadata.json is a pure cache — TTL'd browser/driver version lookups plus last_used stamps for cache pruning. Losing it costs one round of re-discovery, nothing more. Today in rust/src/metadata.rs:
| Failure | Current behaviour |
|---|---|
| File absent | new_metadata(log) — empty cache |
Unparseable JSON (metadata.rs:110) |
Err(_e) => new_metadata(log) — empty cache, silently |
Write fails (metadata.rs:243) |
log.warn("Metadata cannot be written in cache ...") |
Delete fails (metadata.rs:262) |
log.warn("Error deleting metadata file: ...") |
Open fails (metadata.rs:102) |
panic |
The open-fails arm is functionally indistinguishable from the unparseable-JSON arm — in both cases the cache is unusable and the obvious recovery is "carry on with an empty cache" — yet it is the only one that stops Selenium Manager entirely. The scenario that surfaced this (running Selenium inside a nono sandbox, reported in #18087) is exactly the case where degrading would let things work. Same applies to a cache file left root-owned by an earlier sudo run, or a read-only mount.
🔧 Proposed change
Treat an unopenable metadata file the same as an unparseable one:
let metadata_file = match File::open(&metadata_path) {
Ok(file) => file,
Err(err) => {
log.warn(format!(
"Metadata file {} cannot be opened: {}. Using empty metadata",
metadata_path.display(),
err
));
return new_metadata(log);
}
};Worth deciding at the same time whether the unparseable-JSON arm should warn rather than discard silently — right now a corrupt cache is invisible even at --debug.
🧪 Test gap
Neither graceful-degradation arm has any coverage. rust/tests/cache_unit_tests.rs exercises get_metadata/write_metadata round-trips against a tempdir(), but nothing drives a bad cache through get_metadata. The corrupt-JSON fallback at metadata.rs:110 is the cheap, portable one to pin:
#[test]
fn unparseable_metadata_falls_back_to_empty() {
let tmp = tempdir().unwrap();
let cache = tmp.path().to_path_buf();
fs::write(cache.join("se-metadata.json"), "{ not json").unwrap();
let meta = get_metadata(&Logger::default(), &Some(cache));
assert!(meta.drivers.is_empty() && meta.browsers.is_empty());
}A permission-denial equivalent is harder and lower value: 0o000 is readable by root, so the test would go red (not silently green) in root CI containers unless it self-guards, and there is no precedent for permission-denial tests in rust/ today — the only set_permissions in rust/tests is browser_tests.rs:254, granting 0o755. The corrupt-JSON test pins the same invariant without the portability cost.
📝 Note
Separately, and not worth a change on its own: panic! introduced by #18087 is the first explicit panic in rust/src (grep -rn 'panic!(\|\.expect(' rust/src is otherwise empty). The crate's convention for fatal user-facing errors is log.error(...) + flush_and_exit(DATAERR, ...) in main.rs, which emits the JSON envelope the bindings parse; a panic exits 101 before log.flush() runs, so bindings surface the text as an unparsed dump. Adopting the fallback above makes this moot.
Activity
AutomatedTester commentedon Sep 29, 2026
removing the link as this is a following on task, we don't want this issue closed
[rust] Degrade to empty metadata when the cache cannot be read (Selen…