schollz/croc · error · Error

Received a file position that is too large

Error message

Received a file position that is too large

What it means

Thrown by DataReceiver.read when the 8-byte little-endian position prefix of a chunk exceeds Number.MAX_SAFE_INTEGER (2^53-1). Positions must map to safe JavaScript numbers for offset math, so a larger value cannot be a legitimate file offset (it would imply an exabyte-scale file). It indicates a corrupted frame or a hostile/buggy sender.

Source

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

    this.fail(new Error("Data receiver stopped"));
  }

  private async read(socket: CrocSocket) {
    const engine = wasm();
    while (!this.stopped) {
      try {
        let payload = await engine.decrypt(await socket.receive(), this.key);
        if (!this.noCompress) {
          payload = await engine.decompress(payload, MAX_DECOMPRESSED_CHUNK_SIZE);
        }
        if (payload.byteLength < 9) throw new Error("Received an invalid file chunk");
        const positionBig = new DataView(
          payload.buffer,
          payload.byteOffset,
          payload.byteLength,
        ).getBigUint64(0, true);
        if (positionBig > BigInt(Number.MAX_SAFE_INTEGER)) {
          throw new Error("Received a file position that is too large");
        }
        const position = Number(positionBig);
        const bytes = payload.slice(8);
        await this.accept(position, bytes);
      } 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;
  }

View on GitHub (pinned to e25f1bdc04)

Solutions

  1. Reproduce with the same file and code phrase to distinguish transient corruption from deterministic encoding bugs
  2. Verify sender and recipient wasm builds match (same engine for setBigUint64 little-endian framing)
  3. Run the transfer over a different relay/network to rule out path corruption
  4. If interoperating with external clients, confirm they use the same 8-byte LE position framing
Defensive patterns

Strategy: validation

Validate before calling

if (!Number.isSafeInteger(file.size) || file.size > Number.MAX_SAFE_INTEGER) {
  throw new Error(`File too large to transfer: ${file.name}`);
}

Type guard

function isSafeChunkPosition(positionBig: bigint): boolean {
  return positionBig >= 0n && positionBig <= BigInt(Number.MAX_SAFE_INTEGER);
}

Try / catch

catch (e) {
  if (e instanceof Error && e.message === "Received a file position that is too large") {
    // corrupted or hostile chunk: abort transfer, do not retry the same session
  }
  throw e;
}

Prevention

When it happens

Trigger: Corrupted plaintext after decrypt/decompress where the first 8 bytes decode to a huge uint64; sender writes an unaligned or wrong-endian position; malicious peer deliberately crafting positions above 2^53; decompression bomb or misinterpretation of a non-chunk payload as a chunk.

Common situations: Wasm compress/decompress skew between peer builds; wrong decryption key producing plausible-length garbage; fuzzing or adversarial testing of the data channel; a modified sender that changes the position encoding.

Related errors


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