Skip to content

[rust] Selenium Manager panics instead of degrading when the metadata cache cannot be read #18088

Closed

Description

@AutomatedTester

💬 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

  1. AutomatedTester commented on Sep 29, 2026

    @AutomatedTester
    MemberAuthor

    removing the link as this is a following on task, we don't want this issue closed

  2. added a commit that references this issue on Oct 1, 2026
    1bb320f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

B-managerSelenium ManagerC-rustRust code is mostly Selenium Manager

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions