{"record":{"id":"17c99eecb0c2f92d","repo":"moeru-ai/airi","slug":"invalid-vram-override-bytes-expected-null-or","errorCode":null,"errorMessage":"Invalid VRAM override: ${bytes} (expected null or non-negative finite number)","messagePattern":"Invalid VRAM override: (.+?) \\(expected null or non-negative finite number\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-shared/src/webgpu/detect.ts","lineNumber":226,"sourceCode":" * Simple boolean helper that matches the old `isWebGPUSupported()` API.\n * Prefer `detectWebGPU()` when you need more detail.\n */\nexport async function isWebGPUSupported(): Promise<boolean> {\n  // Fast-path: if gpuu's lightweight check is enough\n  return gpuuIsSupported()\n}\n\n/**\n * Override the estimated VRAM value. Pass `null` to clear the override and\n * revert to the heuristic. The override applies to future detections, and if\n * a result is already cached its VRAM fields are updated immediately, so\n * `resetWebGPUCache()` is not required.\n *\n * Intended for user preference UI (\"I have 8 GB VRAM\") and testing.\n */\nexport function setEstimatedVRAMOverride(bytes: number | null): void {\n  if (bytes !== null && (!Number.isFinite(bytes) || bytes < 0))\n    throw new Error(`Invalid VRAM override: ${bytes} (expected null or non-negative finite number)`)\n\n  vramOverride = bytes\n\n  // If we already have a cached result, update it in-place so consumers\n  // see the new value without needing to call resetWebGPUCache(). The\n  // original heuristic value is preserved in `cachedHeuristicVRAM` so we\n  // can revert when the override is cleared.\n  if (cachedResult) {\n    const vram = resolveVRAM(cachedHeuristicVRAM)\n    cachedResult = {\n      ...cachedResult,\n      estimatedVRAM: vram.bytes,\n      estimatedVRAMSource: vram.source,\n    }\n  }\n}\n\n/** Read the current VRAM override, or null if unset. */","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-shared/src/webgpu/detect.ts#L208-L244","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Parse and validate before calling: const n = Number(value); if (value === null || (Number.isFinite(n) && n >= 0)) setEstimatedVRAMOverride(value === null ? null : n)","Convert units explicitly: GB input -> bytes via Math.round(gb * 1024**3)","Use null (not -1 or 0-by-accident) to clear the override — 0 is a legitimate value and will not clear it","Store the preference as a number (JSON) so it round-trips without re-parsing"],"exampleFix":"// before\nsetEstimatedVRAMOverride(parseFloat(input)) // NaN when input === '8 GB'\n\n// after\nconst parsed = /^\\s*(\\d+(?:\\.\\d+)?)\\s*(gb)?\\s*$/i.exec(input)\nif (!parsed) throw new Error('Enter a value like \"8\" or \"8 GB\"')\nsetEstimatedVRAMOverride(Math.round(Number.parseFloat(parsed[1]) * 1024 ** 3))","handlingStrategy":"validation","validationCode":"function toVRAMOverride(value: string | number | null): number | null {\n  if (value === null || value === '') return null\n  const n = typeof value === 'number' ? value : Number(value.replace(/gb/i, '').trim())\n  if (!Number.isFinite(n) || n < 0) return null // or throw a user-facing message\n  return Math.round(n * (/(?<=\\d)\\s*gb/i.test(String(value)) ? 1024 ** 3 : 1))\n}\nsetEstimatedVRAMOverride(toVRAMOverride(userInput))","typeGuard":"const isVRAMOverride = (v: unknown): v is number | null => v === null || (typeof v === 'number' && Number.isFinite(v) && v >= 0)","tryCatchPattern":"catch (e) { if (e.message.includes('Invalid VRAM override')) { resetInputToNull(); return } throw e }","preventionTips":["Normalize units (GB vs bytes) before calling","Pass null, never -1, to clear the override","Store the preference as a number so it round-trips without parsing"],"tags":["webgpu","vram","numeric-validation","user-preferences"],"backgroundTag":"invalid-numeric-input","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}