{"record":{"id":"5b53ce0cf03761fc","repo":"koala73/worldmonitor","slug":"worksheet-json-must-be-no-larger-than-64-kib","errorCode":null,"errorMessage":"Worksheet JSON must be no larger than 64 KiB.","messagePattern":"Worksheet JSON must be no larger than 64 KiB\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/components/OperationalExposureForm.ts","lineNumber":147,"sourceCode":"    editor.append(section);\n  }\n  editor.prepend(h('section', { className: 'operational-input-section' }, h('h3', {}, 'Operation inputs'), fields));\n  root.append(h('header', { className: 'operational-header' },\n    h('p', { className: 'operational-eyebrow' }, 'LOCAL WORKSHEET'),\n    h('h2', { className: 'cdp-card-title' }, 'Operational what-if'),\n    h('p', { className: 'cdp-section-description' }, 'Compare usable stock, daily demand and delivery timing. Edit the labeled example to test your assumptions.')));\n  root.addEventListener('input', event => {\n    if (event.target instanceof HTMLInputElement && event.target.type !== 'file') { event.target.setCustomValidity(''); basis = 'user'; update(); }\n  });\n  const file = input('Import worksheet JSON', 'file', actions);\n  file.accept = '.json,application/json';\n  file.addEventListener('change', async () => {\n    const selected = file.files?.[0];\n    if (!selected) return;\n    const current = revision;\n    const generation = ++importGeneration;\n    try {\n      if (selected.size > MAX_OPERATIONAL_JSON_BYTES) throw new Error('Worksheet JSON must be no larger than 64 KiB.');\n      const imported = importOperationalWorksheet(await selected.text());\n      if (signal?.aborted || generation !== importGeneration) return;\n      if (current !== revision) throw new Error('Inputs changed while reading. Select the file again to import.');\n      populate(imported.input); importStatus.textContent = 'Worksheet imported. Results recalculated from its inputs.';\n    } catch (cause) {\n      importStatus.textContent = `Import rejected; your inputs are unchanged. ${cause instanceof Error ? cause.message : 'Invalid JSON.'}`;\n    } finally { if (generation === importGeneration) file.value = ''; }\n  });\n  exportButton.addEventListener('click', () => {\n    if (!snapshot) return;\n    const url = URL.createObjectURL(new Blob([JSON.stringify(snapshot, null, 2)], { type: 'application/json' }));\n    h('a', { href: url, download: 'operational-worksheet.json' }).click();\n    setTimeout(() => URL.revokeObjectURL(url), 30_000);\n  });\n  actions.append(exportButton);\n  root.append(actions, importStatus,\n    h('details', { className: 'operational-method operational-input-help' }, h('summary', {}, 'How this worksheet works'),\n      h('p', {}, 'Actual operating data is optional. Inputs stay in browser memory until page reload; export JSON to keep them. Use one unit for all quantities. Changing the unit relabels all quantities; it does not convert them. Up to 90 days and 30 deliveries per list. Quantities and costs allow 0-1 million with up to 6 decimal places.')),","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/koala73/worldmonitor/blob/7d06c8633d256c18e38133030bc3613976a96ec9/src/components/OperationalExposureForm.ts#L129-L165","documentation":"The operational exposure form's file-import handler rejects any selected worksheet JSON file larger than MAX_OPERATIONAL_JSON_BYTES (64 KiB) before it is parsed. The check runs on selected.size immediately after the change event, so oversized files never reach importOperationalWorksheet.","triggerScenarios":"Selecting a worksheet .json file in the import file input whose size exceeds 64 KiB (65536 bytes), regardless of content validity.","commonSituations":"Exporting a worksheet from a session with many inputs/history and re-importing it; hand-edited worksheets with embedded data dumps; importing a full dashboard export instead of the single worksheet export.","solutions":["Reduce the worksheet's size: remove extra fields, whitespace, or embedded data before re-exporting.","Re-export the worksheet from the form's export button instead of importing an unrelated large JSON file.","Minify the JSON (strip indentation) if it is under the limit once pretty-printing is removed.","Split inputs across multiple worksheets if the model genuinely needs more than 64 KiB of input."],"exampleFix":"// before\nconst text = await selected.text();\nconst imported = importOperationalWorksheet(text);\n// after\nif (selected.size > 64 * 1024) {\n  const minified = JSON.stringify(JSON.parse(await selected.text()));\n  if (minified.length > 64 * 1024) throw new Error('Worksheet JSON must be no larger than 64 KiB.');\n  var imported = importOperationalWorksheet(minified);\n} else {\n  var imported = importOperationalWorksheet(await selected.text());\n}","handlingStrategy":"validation","validationCode":"const input = document.querySelector('input[type=file]');\ninput.addEventListener('change', () => {\n  const f = input.files?.[0];\n  if (f && f.size > 64 * 1024) { alert('Worksheet must be ≤ 64 KiB'); input.value = ''; }\n});","typeGuard":null,"tryCatchPattern":"try {\n  await importWorksheet(file);\n} catch (e) {\n  if (e.message.includes('64 KiB')) setStatus('File too large — export a smaller worksheet (≤ 64 KiB).');\n  else setStatus('Import rejected; your inputs are unchanged.');\n}","preventionTips":["Check file.size in the change handler before reading the file.","Export worksheets minified to stay well under 64 KiB.","Educate users that worksheet exports are input-only, not full data dumps."],"tags":["file-import","size-limit","validation","ui"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"7d06c8633d256c18e38133030bc3613976a96ec9","analyzedAt":"2026-09-15T16:44:39.439Z","contentChangedAt":"2026-09-15T16:44:39.439Z","schemaVersion":2},"datasetVersion":"2026-09-15T18:17:12.389Z"}