duplicati/duplicati · error · FileMissingException

FileMissing

FileMissing

Error message

The requested file does not exist

What it means

Thrown inside the private Info() method when the JFS GET for a single file returns HTTP 404 NotFound. Info() is called by ParallelGetAsync to learn the file size before chunking, so this surfaces during parallel downloads.

Source

Thrown at Duplicati/Library/Backend/Jottacloud/Jottacloud.cs:309

        (var client, var _) = await GetClient(cancelToken).ConfigureAwait(false);
        var doc = new System.Xml.XmlDocument();
        try
        {
            // Send request and load XML response.
            using var req = await CreateRequest(HttpMethod.Get, remotename, "", false, cancelToken).ConfigureAwait(false);

            using var response = await Utility.Utility.WithTimeout(m_timeouts.ListTimeout, cancelToken,
                    innerCancellationToken =>
                        client.GetResponseAsync(req, HttpCompletionOption.ResponseHeadersRead, innerCancellationToken))
                .ConfigureAwait(false);

            await using var rs = await response.Content.ReadAsStreamAsync(cancelToken).ConfigureAwait(false);
            doc.Load(rs);
        }
        catch (HttpRequestException wex)
        {
            if (wex.StatusCode == HttpStatusCode.NotFound)
                throw new FileMissingException(wex);
            throw;
        }

        // Handle XML response. Since we in the constructor demand a folder below the mount point we know the root
        // element must be a "folder", else it could also have been a "mountPoint" (which has a very similar structure).
        // We must check for "deleted" attribute, because files/folders which has it is deleted (attribute contains the timestamp of deletion)
        // so we treat them as non-existent here.
        var xFile = doc.DocumentElement;
        if (xFile?.Attributes["deleted"] != null)
            throw new FileMissingException($"{LC.L("The requested file does not exist")}: {remotename}");

        return ToFileEntry(xFile);
    }

    /// <inheritdoc/>
    public async Task PutAsync(string remotename, string filename, CancellationToken cancelToken)
    {
        await using var fs = File.OpenRead(filename);

View on GitHub (pinned to 3f348be3e3)

Solutions

  1. Verify the file appears in ListAsync output before downloading.
  2. If a concurrent operation deletes files, serialize or re-list before each get.
  3. Treat as transient and retry once the expected file is present.
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm the file is listed before parallel download
var exists = false;
await foreach (var e in backend.ListAsync(token))
    if (e.Name == remotename) { exists = true; break; }
if (!exists) throw new FileNotFoundException(remotename);

Try / catch

try { await backend.GetAsync(remotename, dest, token); }
catch (FileMissingException ex) { logger.LogWarning("File gone: {Message}", ex.Message); /* skip or re-list */ }

Prevention

When it happens

Trigger: Requesting Info (via GetAsync with m_threads > 1) for a remotename that does not exist on the server, or that was deleted between the list call and the get call.

Common situations: A backup block file was already deleted by a concurrent purge; the remote name is misspelled; another client removed the file; an interrupted prior run left the remote state inconsistent.

Related errors


AI-assisted analysis of duplicati/duplicati@3f348be3e3 (2026-08-13). Data as JSON: /api/errors/0fc002c7b6919d4d. Report an issue: GitHub.