dotnet/aspnetcore · error · Error

Cannot read uint64 with high order part ${highPart}, because

Error message

Cannot read uint64 with high order part ${highPart}, because the result would exceed Number.MAX_SAFE_INTEGER.

What it means

Thrown by readUint64LE in BinaryDecoder when the high-order 32 bits of a little-endian uint64 read from a serialized interop buffer exceed 2^21-1, because combining such a high part with any low part would exceed Number.MAX_SAFE_INTEGER (2^53-1) and lose precision. The framework deliberately refuses rather than silently corrupt large ulong values.

Source

Thrown at src/Components/Web.JS/src/BinaryDecoder.ts:26

  return (buffer[position])
        | (buffer[position + 1] << 8)
        | (buffer[position + 2] << 16)
        | (buffer[position + 3] << 24);
}

export function readUint32LE(buffer: Uint8Array, position: number): any {
  return (buffer[position])
        + (buffer[position + 1] << 8)
        + (buffer[position + 2] << 16)
        + ((buffer[position + 3] << 24) >>> 0); // The >>> 0 coerces the value to unsigned
}

export function readUint64LE(buffer: Uint8Array, position: number): any {
  // This cannot be done using bit-shift operators in JavaScript, because
  // those all implicitly convert to int32
  const highPart = readUint32LE(buffer, position + 4);
  if (highPart > maxSafeNumberHighPart) {
    throw new Error(`Cannot read uint64 with high order part ${highPart}, because the result would exceed Number.MAX_SAFE_INTEGER.`);
  }

  return (highPart * uint64HighPartShift) + readUint32LE(buffer, position);
}

export function readLEB128(buffer: Uint8Array, position: number): number {
  let result = 0;
  let shift = 0;
  for (let index = 0; index < 4; index++) {
    const byte = buffer[position + index];
    result |= (byte & 127) << shift;
    if (byte < 128) {
      break;
    }
    shift += 7;
  }
  return result;
}

View on GitHub (pinned to 3600ca084e)

Solutions

  1. Pass large uint64 values as strings (toString()) instead of as native ulong, and parse on the receiving side with BigInt.
  2. Change the parameter/return type to long (signed) only if values stay within safe integer range — this does not raise the ceiling.
  3. Reduce the magnitude: send a derived/scaled value that fits in 53 bits and reconstruct on the other side.
  4. Where possible, store large IDs as string on the .NET side so they never transit as numeric uint64.

Example fix

// before — passing a snowflake ID as ulong throws when JS decodes it
[Parameter] public ulong UserId { get; set; } // 64-bit value > 2^53

// after — serialize as string and parse with BigInt in JS
[Parameter] public string UserId { get; set; } // .NET: userId.ToString()
// JS: const id = BigInt(user.userId);
Defensive patterns

Strategy: validation

Validate before calling

// Pass large uint64 values as strings; never as native ulong through interop.
const MAX_SAFE = Number.MAX_SAFE_INTEGER;
function safeUlong(value) {
  return value > MAX_SAFE ? value.toString() : value;
}

Type guard

function isSafeUint64(n) {
  return Number.isInteger(n) && n >= 0 && n <= Number.MAX_SAFE_INTEGER;
}

Try / catch

try {
  await dotNet.invokeMethodAsync('PassId', bigId);
} catch (e) {
  if (/exceed Number.MAX_SAFE_INTEGER/.test(e.message)) {
    await dotNet.invokeMethodAsync('PassId', bigId.toString());
  } else throw e;
}

Prevention

When it happens

Trigger: Serializing a System.UInt64 (or ulong) whose value is greater than ~2^53-1 (9,007,199,254,740,991) into a binary interop payload that Blazor's BinaryDecoder later reads. Common with large counters, snowflake IDs, timestamps in ticks, file sizes, or memory offsets.

Common situations: Twitter/Discord snowflake IDs, large primary keys, DateTime/Stopwatch ticks beyond safe range, file/stream offsets, high-resolution timestamps, or any ulong field flowing through JS interop.

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/333c235e370a895a. Report an issue: GitHub.