From 7e265f3e30e0972a00c8d4900d9effaf4f9a66ee Mon Sep 17 00:00:00 2001 From: mARTin-B78 Date: Sun, 28 Jun 2026 00:36:18 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20null-safe=20loadSettings()=20=E2=80=94?= =?UTF-8?q?=20prevent=20crash=20on=20missing=20elements=20(v1.12.17)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit loadSettings() was crashing with "Cannot set properties of null" because many settings input elements were moved out of their original sections during the Library restructure. All bare .value assignments are now routed through a local sv() helper that silently skips absent elements. This was also blocking My Voices from rendering on page load. Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 7 +++++ static/index.html | 4 +-- static/js/settings.js | 68 +++++++++++++++++++++---------------------- 3 files changed, 43 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0027dfb..9713c4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,13 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi --- +## [1.12.17] — 2026-06-28 + +### Fixed +- **Settings load crash** — `loadSettings()` used direct `.value` assignments on elements that no longer exist after the Library restructure; all now use null-safe `sv()` helper so a missing element is silently skipped instead of throwing. This was also preventing My Voices from loading on page start. + +--- + ## [1.12.16] — 2026-06-28 ### Added diff --git a/static/index.html b/static/index.html index ad5d487..f39b4c6 100644 --- a/static/index.html +++ b/static/index.html @@ -26,7 +26,7 @@ - + @@ -336,7 +336,7 @@ - + diff --git a/static/js/settings.js b/static/js/settings.js index 36a7a8d..edee38e 100644 --- a/static/js/settings.js +++ b/static/js/settings.js @@ -399,16 +399,17 @@ function enhanceSettingsHelp(root = document) { async function loadSettings() { const s = await fetch('/api/settings').then(r => r.json()); - $('s-whisper-url').value = s.whisper_url || ''; - $('s-whisper-key').value = s.whisper_api_key || ''; - $('s-tts-url').value = s.tts_url || ''; - $('s-faster-whisper-url').value = s.faster_whisper_url || ''; - $('s-whisper-cpp-url').value = s.whisper_cpp_url || ''; - $('s-groq-api-key').value = s.groq_api_key || ''; - $('s-kokoro-url').value = s.kokoro_url || ''; - $('s-vibevoice-url').value = s.vibevoice_url || ''; - $('s-xtts-url').value = s.xtts_url || ''; - const llmUrlEl = $('s-llm-url'); if (llmUrlEl) llmUrlEl.value = s.llm_url || ''; + const sv = (id, val) => { const el = $(id); if (el) el.value = val; }; + sv('s-whisper-url', s.whisper_url || ''); + sv('s-whisper-key', s.whisper_api_key || ''); + sv('s-tts-url', s.tts_url || ''); + sv('s-faster-whisper-url', s.faster_whisper_url || ''); + sv('s-whisper-cpp-url', s.whisper_cpp_url || ''); + sv('s-groq-api-key', s.groq_api_key || ''); + sv('s-kokoro-url', s.kokoro_url || ''); + sv('s-vibevoice-url', s.vibevoice_url || ''); + sv('s-xtts-url', s.xtts_url || ''); + sv('s-llm-url', s.llm_url || ''); _appSettings = s; // Restore engine URL inputs from server (overrides localStorage fallback) @@ -437,32 +438,31 @@ async function loadSettings() { if (refineInp && s.refine_llm_url) refineInp.value = s.refine_llm_url; const convInp = $('conv-llm-url'); if (convInp && s.conv_llm_url) convInp.value = s.conv_llm_url; - $('s-tts-stream-url').value = s.tts_stream_url || ''; - $('s-customvoice-url').value = s.customvoice_url || 'http://host.docker.internal:8022'; - $('s-nvidia-router-url').value = s.nvidia_router_url || 'http://host.docker.internal:8090'; - $('s-nvidia-tts-url').value = s.nvidia_tts_url || 'http://host.docker.internal:8091'; - $('s-nvidia-asr-url').value = s.nvidia_asr_url || 'http://host.docker.internal:8092'; - $('s-nvidia-zeroshot-url').value = s.nvidia_zeroshot_url || s.nvidia_clone_url || 'http://host.docker.internal:8093'; - $('s-nvidia-flow-url').value = s.nvidia_flow_url || 'http://host.docker.internal:8094'; - $('s-tts-stream-mode').value = s.tts_stream_mode || 'auto'; - $('s-tts-key').value = s.tts_api_key || ''; - $('s-tts-backend').value = s.tts_backend || 'openai'; + sv('s-tts-stream-url', s.tts_stream_url || ''); + sv('s-customvoice-url', s.customvoice_url || 'http://host.docker.internal:8022'); + sv('s-nvidia-router-url', s.nvidia_router_url || 'http://host.docker.internal:8090'); + sv('s-nvidia-tts-url', s.nvidia_tts_url || 'http://host.docker.internal:8091'); + sv('s-nvidia-asr-url', s.nvidia_asr_url || 'http://host.docker.internal:8092'); + sv('s-nvidia-zeroshot-url', s.nvidia_zeroshot_url || s.nvidia_clone_url || 'http://host.docker.internal:8093'); + sv('s-nvidia-flow-url', s.nvidia_flow_url || 'http://host.docker.internal:8094'); + sv('s-tts-stream-mode', s.tts_stream_mode || 'auto'); + sv('s-tts-key', s.tts_api_key || ''); + sv('s-tts-backend', s.tts_backend || 'openai'); const defaultTtsParams = {temperature:0.1, top_p:0.8, seed:0}; const byBackend = s.tts_extra_params_by_backend || {}; - $('s-tts-extra-voice-clone').value = JSON.stringify(byBackend.voice_clone || s.tts_extra_params || defaultTtsParams, null, 2); - $('s-tts-extra-streaming').value = JSON.stringify(byBackend.streaming || s.tts_extra_params || defaultTtsParams, null, 2); - $('s-tts-extra-customvoice').value = JSON.stringify(byBackend.customvoice || s.tts_extra_params || defaultTtsParams, null, 2); - $('s-tts-extra-voice-design').value = JSON.stringify(byBackend.voice_design || s.tts_extra_params || defaultTtsParams, null, 2); - $('s-tts-extra-nvidia-magpie').value = JSON.stringify(byBackend.nvidia_magpie || {}, null, 2); - $('s-tts-extra-nvidia-zeroshot').value = JSON.stringify(byBackend.nvidia_zeroshot || {}, null, 2); - $('s-tts-extra-nvidia-flow').value = JSON.stringify(byBackend.nvidia_flow || {}, null, 2); - $('s-tts-extra-kokoro').value = JSON.stringify(byBackend.kokoro || {}, null, 2); - const vibevoiceExtraEl = $('s-tts-extra-vibevoice'); - if (vibevoiceExtraEl) vibevoiceExtraEl.value = JSON.stringify(byBackend.vibevoice || {}, null, 2); - $('s-voice-design-url').value = s.voice_design_url || 'http://host.docker.internal:8021'; - $('s-vd-key').value = s.voice_design_api_key || ''; - $('s-voices-scan-dir').value = s.voices_scan_dir || ''; - $('s-output-dir').value = s.output_dir || ''; + sv('s-tts-extra-voice-clone', JSON.stringify(byBackend.voice_clone || s.tts_extra_params || defaultTtsParams, null, 2)); + sv('s-tts-extra-streaming', JSON.stringify(byBackend.streaming || s.tts_extra_params || defaultTtsParams, null, 2)); + sv('s-tts-extra-customvoice', JSON.stringify(byBackend.customvoice || s.tts_extra_params || defaultTtsParams, null, 2)); + sv('s-tts-extra-voice-design', JSON.stringify(byBackend.voice_design || s.tts_extra_params || defaultTtsParams, null, 2)); + sv('s-tts-extra-nvidia-magpie', JSON.stringify(byBackend.nvidia_magpie || {}, null, 2)); + sv('s-tts-extra-nvidia-zeroshot',JSON.stringify(byBackend.nvidia_zeroshot|| {}, null, 2)); + sv('s-tts-extra-nvidia-flow', JSON.stringify(byBackend.nvidia_flow || {}, null, 2)); + sv('s-tts-extra-kokoro', JSON.stringify(byBackend.kokoro || {}, null, 2)); + sv('s-tts-extra-vibevoice', JSON.stringify(byBackend.vibevoice || {}, null, 2)); + sv('s-voice-design-url', s.voice_design_url || 'http://host.docker.internal:8021'); + sv('s-vd-key', s.voice_design_api_key || ''); + sv('s-voices-scan-dir', s.voices_scan_dir || ''); + sv('s-output-dir', s.output_dir || ''); const seedFinderDirEl = $('s-seed-finder-dir'); if (seedFinderDirEl) seedFinderDirEl.value = s.seed_finder_dir || ''; const ptDirEl = $('s-pt-dir');