duplicati/duplicati · error · InvalidOperationException
Invalid file size for {remotename}
Error message
Invalid file size for {remotename} What it means
Thrown in ParallelGetAsync when info.Size is negative. ToFileEntry sets size to -1 when the <size> element is missing or not a parseable long, so a < 0 size means the file metadata is absent or corrupt.
Source
Thrown at Duplicati/Library/Backend/Jottacloud/Jottacloud.cs:468
await using var s = await response.Content.ReadAsStreamAsync(cancelToken).ConfigureAwait(false);
await using var t = s.ObserveReadTimeout(m_timeouts.ReadWriteTimeout);
await Utility.Utility.CopyStreamAsync(s, stream, true, cancelToken).ConfigureAwait(false);
}
/// <summary>
/// Fetches the file in chunks (parallelized)
/// </summary>
private async Task ParallelGetAsync(string remotename, Stream stream, CancellationToken cancelToken)
{
// Get file info and validate
var info = await Info(remotename, cancelToken).ConfigureAwait(false);
if (info == null)
throw new FileMissingException(remotename);
var size = info.Size;
if (size < 0)
throw new InvalidOperationException($"Invalid file size for {remotename}");
// Calculate chunks with bounds checking
var chunks = new Queue<(long start, long end)>();
long position = 0;
while (position < size)
{
var length = Math.Min(m_chunksize, size - position);
if (length <= 0)
throw new InvalidOperationException($"Invalid chunk length calculated for {remotename}");
chunks.Enqueue((position, position + length));
position += length;
}
var tasks = new List<Task<(byte[] buffer, long start, Exception? error)>>();
var completedChunks = new SortedDictionary<long, byte[]>();
var semaphore = new SemaphoreSlim(m_threads, m_threads);
long nextWritePosition = 0;
View on GitHub (pinned to 3f348be3e3)
Solutions
- Re-upload the file to regenerate clean metadata.
- Fall back to single-threaded download (jottacloud-threads=1) which does not need the size for chunking.
- Inspect the raw XML for the file via a direct JFS GET to confirm the size element.
Example fix
// before --jottacloud-threads=4 // ParallelGetAsync needs a valid size // after --jottacloud-threads=1 // GetAsync streams without chunk math
Defensive patterns
Strategy: fallback
Validate before calling
// Prefer single-threaded get when file metadata is unreliable if (threads <= 1) await backend.GetAsync(name, dest, token); // streams without size math
Try / catch
try { await backend.GetAsync(remotename, dest, token); /* threads > 1 */ }
catch (InvalidOperationException ex) when (ex.Message.Contains("Invalid file size"))
{
// fall back to single-threaded streaming download that does not need the size
} Prevention
- Set jottacloud-threads=1 for files with unreliable or missing size metadata.
- Re-upload files whose <size> metadata is absent or corrupt.
- Inspect the raw JFS XML for the file to confirm the size element before chunking.
When it happens
Trigger: The file's currentRevision XML lacks a <size> child or contains a non-numeric <size>, causing ToFileEntry to default size to -1, which then fails the size >= 0 guard before chunking.
Common situations: Server-side metadata corruption; the file is in an unusual state (e.g. only a corrupt latestRevision); a JFS API response-format change dropped or renamed the size element.
Related errors
- Invalid Content-Range response for chunk {chunk.start}-{chun
- Unexpected buffer size for chunk {chunk.start}-{chunk.end -
- Stream position mismatch after download for {remotename}
- Invalid file size {0}, expected {1} for {2}
- Damaged or corrupted file, sha256 mismatch for {0}
AI-assisted analysis of duplicati/duplicati@3f348be3e3 (2026-08-13).
Data as JSON: /api/errors/c327218a4152276a.
Report an issue: GitHub.