Skip to content

REST backend: an error status on HEAD /config reads as "no config file" #652

Open

Description

@nledford

rustic_core: 01fe284 (still the same on main at d658ed9, 2026-11-09)

What happens

RestBackend::list_with_size(FileType::Config) checks for the config file with a HEAD request and treats every non-success status as "the file is not there":

if tpe == FileType::Config {
    return Ok(
        if self.client.head(url.clone()).send().await?.status().is_success() {
            vec![(Id::default(), 0)]
        } else {
            Vec::new()
        },
    );
}

Only a transport error comes back as Err. A 401 Unauthorized, 403 Forbidden or 500 Internal Server Error gives an empty list, the same as a 404 Not Found.

Repository::config_id() turns that empty list into Ok(None) (01fe284 repository.rs#L320-L324, main repository.rs#L320-L324), so:

  • open reports "No repository config file found" (01fe284 repository.rs#L381-L389) when the server refused the credentials or failed, which points the user at the wrong problem;
  • init finds no config (01fe284 repository.rs#L464-L475) and goes on to try writing a new repository's key and config, where it should have stopped with the server's error;
  • a caller can't use config_id() to tell "there is no repository here" from "the server didn't answer the question".

rclone's backend serves the REST protocol, so it behaves the same way.

To reproduce

Point a REST repository at a server that answers every request with 401 (or 500), then call Repository::config_id(): it returns Ok(None). Repository::open fails with "No repository config file found" rather than with the status.

Suggestion

Return "absent" only for 404 Not Found and an error for any other non-success status, e.g. by calling error_for_status() after the 404 check, as the other requests in this file already do. The OpenDAL backend's config_exists already works this way: only NotFound reads as absent.

Related

The local backend's config check (path.join("config").exists()) also reads a folder it can't access (permission denied) as "no config"; try_exists() would keep the error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    S-triageStatus: Waiting for a maintainer to triage this issue/PR

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions