schollz/croc · error · Error

Received a file chunk outside the advertised file size

Error message

Received a file chunk outside the advertised file size

What it means

Thrown inside DataReceiver's chunk validation when a chunk fails structural checks: negative position, position not aligned to the 32 KiB CHUNK_SIZE grid, zero-length payload, payload larger than CHUNK_SIZE, or a position+length that exceeds the advertised file size from the sender's fileinfo. These invariants let the receiver write chunks directly at offsets without reassembly logic, so any violation aborts the transfer.

Source

Thrown at web/src/protocol/client.ts:624

  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");
      }
    });
    active.queue.catch((error) => {
      if (this.active === active) this.active = undefined;
      active.reject(error instanceof Error ? error : new Error(String(error)));
    });
    return active.queue;
  }

View on GitHub (pinned to e25f1bdc04)

Solutions

  1. Keep CHUNK_SIZE identical on both peers — it is a wire-format constant, not a tunable
  2. Ensure files are not modified between prepareFiles and sendFileData; re-run prepareFiles if the underlying File changes
  3. Confirm the advertised size in senderInfo (s: file.size) matches what sendFileData actually slices
  4. When interoperating with croc CLI, verify its chunk size and framing match this client before mixing implementations
Defensive patterns

Strategy: validation

Validate before calling

// Before sending, assert chunk framing invariants the receiver will enforce
const CHUNK_SIZE = 32 * 1024;
function assertChunkOk(position: number, len: number, size: number) {
  if (position < 0 || position % CHUNK_SIZE !== 0 || len === 0 || len > CHUNK_SIZE || position + len > size) {
    throw new Error("Chunk framing violated before send");
  }
}

Type guard

function isAlignedPosition(position: number): boolean {
  return Number.isSafeInteger(position) && position >= 0 && position % (32 * 1024) === 0;
}

Try / catch

catch (e) {
  if (e instanceof Error && e.message === "Received a file chunk outside the advertised file size") {
    // framing/size mismatch between peers: restart transfer after aligning versions
  }
  throw e;
}

Prevention

When it happens

Trigger: Sender uses a different chunk size than 32768 (e.g. croc CLI default 1024*1024 or a changed constant); position encoding mismatch (endian or width); sender's advertised file size (s field) smaller than actual streamed bytes; file truncated on the sender side after prepareFiles hashed it; corruption that alters position or length bytes.

Common situations: CHUNK_SIZE constant changed on one peer but not the other; interoperating with the croc CLI whose chunking differs; sender's File object changes on disk between hashing (prepareFiles) and streaming (sendFileData) so slice() returns fewer/misaligned bytes; version drift in the framing format.

Related errors


AI-assisted analysis of schollz/croc@e25f1bdc04 (2026-08-15). Data as JSON: /api/errors/04ef12db640223f6. Report an issue: GitHub.