moeru-ai/airi · error · Error

Invalid VRAM override

Error message

Invalid VRAM override: ${bytes} (expected null or non-negative finite number)

What it means

Thrown by setEstimatedVRAMOverride in packages/stage-shared/src/webgpu/detect.ts when `bytes` is neither null nor a finite non-negative number. The function explicitly accepts null (to clear the override) and any number >= 0 including 0; NaN, Infinity, and negatives are rejected because they cannot represent a VRAM quantity in bytes.

Solutions

  1. Parse and validate before calling: const n = Number(value); if (value === null || (Number.isFinite(n) && n >= 0)) setEstimatedVRAMOverride(value === null ? null : n)
  2. Convert units explicitly: GB input -> bytes via Math.round(gb * 1024**3)
  3. Use null (not -1 or 0-by-accident) to clear the override — 0 is a legitimate value and will not clear it
  4. Store the preference as a number (JSON) so it round-trips without re-parsing

Example fix

// before
setEstimatedVRAMOverride(parseFloat(input)) // NaN when input === '8 GB'

// after
const parsed = /^\s*(\d+(?:\.\d+)?)\s*(gb)?\s*$/i.exec(input)
if (!parsed) throw new Error('Enter a value like "8" or "8 GB"')
setEstimatedVRAMOverride(Math.round(Number.parseFloat(parsed[1]) * 1024 ** 3))
Defensive patterns

Strategy: validation

Validate before calling

function toVRAMOverride(value: string | number | null): number | null {
  if (value === null || value === '') return null
  const n = typeof value === 'number' ? value : Number(value.replace(/gb/i, '').trim())
  if (!Number.isFinite(n) || n < 0) return null // or throw a user-facing message
  return Math.round(n * (/(?<=\d)\s*gb/i.test(String(value)) ? 1024 ** 3 : 1))
}
setEstimatedVRAMOverride(toVRAMOverride(userInput))

Type guard

const isVRAMOverride = (v: unknown): v is number | null => v === null || (typeof v === 'number' && Number.isFinite(v) && v >= 0)

Try / catch

catch (e) { if (e.message.includes('Invalid VRAM override')) { resetInputToNull(); return } throw e }

Prevention

When it happens

Trigger: Calling setEstimatedVRAMOverride(NaN) after parseFloat fails on input like '8 GB'; passing -1 as a 'no override' sentinel; passing Infinity from a division by zero (bytes / 0); passing a string like '8589934592' instead of a number.

Common situations: Wiring the documented 'I have 8 GB VRAM' preference UI: parsing '8 GB' with Number() yields NaN; unit conversion mistakes (GB vs GiB vs bytes) producing fractional or negative intermediate values; passing a value read from localStorage that was stored as a string.

Related errors


AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18). Data as JSON: /api/errors/17c99eecb0c2f92d. Report an issue: GitHub.

Appendix: source

Thrown at packages/stage-shared/src/webgpu/detect.ts:226

 * Simple boolean helper that matches the old `isWebGPUSupported()` API.
 * Prefer `detectWebGPU()` when you need more detail.
 */
export async function isWebGPUSupported(): Promise<boolean> {
  // Fast-path: if gpuu's lightweight check is enough
  return gpuuIsSupported()
}

/**
 * Override the estimated VRAM value. Pass `null` to clear the override and
 * revert to the heuristic. The override applies to future detections, and if
 * a result is already cached its VRAM fields are updated immediately, so
 * `resetWebGPUCache()` is not required.
 *
 * Intended for user preference UI ("I have 8 GB VRAM") and testing.
 */
export function setEstimatedVRAMOverride(bytes: number | null): void {
  if (bytes !== null && (!Number.isFinite(bytes) || bytes < 0))
    throw new Error(`Invalid VRAM override: ${bytes} (expected null or non-negative finite number)`)

  vramOverride = bytes

  // If we already have a cached result, update it in-place so consumers
  // see the new value without needing to call resetWebGPUCache(). The
  // original heuristic value is preserved in `cachedHeuristicVRAM` so we
  // can revert when the override is cleared.
  if (cachedResult) {
    const vram = resolveVRAM(cachedHeuristicVRAM)
    cachedResult = {
      ...cachedResult,
      estimatedVRAM: vram.bytes,
      estimatedVRAMSource: vram.source,
    }
  }
}

/** Read the current VRAM override, or null if unset. */

View on GitHub (pinned to 677329427f)