schollz/croc · error · Error
Received a duplicate file chunk
Error message
Received a duplicate file chunk
What it means
Thrown inside DataReceiver's per-chunk queue when the same chunk position is delivered twice for the active file. Each position is recorded in active.received on first acceptance, so a repeat means the sender retransmitted a chunk or a data socket duplicated a frame. Because chunk ranges must tile the file exactly once, duplicates abort the transfer rather than being silently ignored.
Source
Thrown at web/src/protocol/client.ts:616
} catch (error) {
if (this.stopped) return;
this.stopped = true;
this.fail(error instanceof Error ? error : new Error(String(error)));
}
}
}
private fail(error: Error) {
this.failure ??= error;
this.active?.reject(error);
this.active = undefined;
}
private accept(position: number, bytes: Uint8Array) {
const active = this.active;
if (!active) throw new Error("Received file data before it was requested");
active.queue = active.queue.then(async () => {
if (active.received.has(position)) throw new Error("Received a duplicate file chunk");
if (
position < 0 ||
position % CHUNK_SIZE !== 0 ||
bytes.byteLength === 0 ||
bytes.byteLength > CHUNK_SIZE ||
position + bytes.byteLength > active.file.size
) {
throw new Error("Received a file chunk outside the advertised file size");
}
active.received.add(position);
await active.sink.writeAt(position, bytes);
active.bytes += bytes.byteLength;
active.progress(active.bytes);
if (active.bytes === active.file.size) {
this.active = undefined;
active.resolve();
} else if (active.bytes > active.file.size) {
throw new Error("Received more data than the advertised file size");View on GitHub (pinned to e25f1bdc04)
Solutions
- Verify both peers open the same number of data connections (relay banner ports) so chunk stride partitioning matches
- If implementing resume, ensure the receiver's received-set and the sender's ranges restart coherently — do not reuse a live DataReceiver across sessions
- Disable or dedupe sender-side retry logic on the data sockets (reliability belongs to the relay/TCP layer)
- Capture the duplicated position value in logs to see whether it is the same index across failures (stride bug) or random (network duplication)
Defensive patterns
Strategy: try-catch
Try / catch
catch (e) {
if (e instanceof Error && e.message === "Received a duplicate file chunk") {
// duplicated frame: abort transfer; dedupe-and-continue is unsafe because chunk accounting breaks
}
throw e;
} Prevention
- Keep the relay banner port list identical on both peers so chunk-to-socket stride partitioning matches
- Do not add sender-side retries on data sockets — the underlying transport is already reliable
- If implementing resume, reset both the sender's ranges and the receiver's state together; never resume one side alone
When it happens
Trigger: Sender retries a failed socket.send and the original frame also arrives; multiple data sockets assigned overlapping chunk indices (stride scheduling bug); relay duplicates a frame; sender re-sends a range after a reconnect while the receiver kept partial state.
Common situations: Flaky connection where sender-side retry logic duplicates frames; reconnect/resume logic that restarts a file from offset 0 while received positions persist; more data sockets on sender than recipient (port list mismatch) shifting chunk-to-socket assignment; proxies that duplicate WebSocket frames.
Related errors
- Received an invalid file chunk
- Received a file position that is too large
- Received file data before it was requested
- Received a file chunk outside the advertised file size
- Received more data than the advertised file size
AI-assisted analysis of schollz/croc@e25f1bdc04 (2026-08-15).
Data as JSON: /api/errors/d052e9918d1ad7fe.
Report an issue: GitHub.