odysseus-dev/odysseus · error · Error

Failed to save

Error message

Failed to save

What it means

Inline settings message shown when saving image-generation settings fails. saveSettings POSTs {image_gen_enabled, image_model, image_quality} to /api/auth/settings; non-OK throws with the response text (or 'HTTP <status>'), and the catch flattens everything to 'Failed to save'.

Source

Thrown at static/js/settings.js:717

    const settings = await settingsRes.json();
    if (settings.image_model) modelSel.value = settings.image_model;
    if (settings.image_quality) qualSel.value = settings.image_quality;
    if (enabledToggle) enabledToggle.checked = settings.image_gen_enabled === true;
  } catch (e) { console.warn('Failed to load settings', e); }

  function syncImgDisabled() {
    var off = enabledToggle && !enabledToggle.checked;
    var card = enabledToggle ? enabledToggle.closest('.admin-card') : null;
    if (card) card.style.opacity = off ? '0.45' : '';
    if (configWrap) configWrap.style.pointerEvents = off ? 'none' : '';
  }
  syncImgDisabled();

  async function saveSettings() {
    try {
      const res = await fetch('/api/auth/settings', { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ image_gen_enabled: enabledToggle ? enabledToggle.checked : false, image_model: modelSel.value, image_quality: qualSel.value }) });
      if (!res.ok) throw new Error(await res.text().catch(() => `HTTP ${res.status}`));
      msg.textContent = 'Saved'; msg.style.color = 'var(--fg)'; setTimeout(() => { msg.textContent = ''; }, 2000);
    } catch (e) { msg.textContent = 'Failed to save'; msg.style.color = 'var(--red)'; }
  }
  modelSel.addEventListener('change', saveSettings);
  qualSel.addEventListener('change', saveSettings);
  if (enabledToggle) enabledToggle.addEventListener('change', function() { syncImgDisabled(); saveSettings(); });
}

/* ── Vision ── */
async function initVisionSettings() {
  const vlSel = el('set-vlModelSelect');
  const msg = el('set-visionSettingsMsg');
  const enabledToggle = el('set-visionEnabledToggle');
  const configWrap = vlSel ? vlSel.closest('div[style*="flex-direction"]') : null;
  var _visionEndpoints = [];
  var visionFallbackWidget = null;
  var _vlExclude = ['audio', 'realtime', 'tts', 'dall-e', 'embedding', 'search', 'whisper'];
  function _isVisionModel(mid) {

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Check devtools for the POST /api/auth/settings status and body
  2. Re-login / confirm the account has permission to change auth settings
  3. Verify model and quality values are ones the backend accepts
  4. Debounce the change-driven autosave and surface e.message instead of a fixed string

Example fix

// before
    } catch (e) { msg.textContent = 'Failed to save'; msg.style.color = 'var(--red)'; }

// after
    } catch (e) {
      console.error('image settings save failed:', e);
      msg.textContent = 'Failed to save: ' + e.message;
      msg.style.color = 'var(--red)';
    }
Defensive patterns

Strategy: try-catch

Validate before calling

if (!navigator.onLine) { msg.textContent = 'Offline'; return; }
if (!modelSel.value || !qualSel.value) { msg.textContent = 'Select model and quality'; return; }

Try / catch

try { const res = await fetch(...); if (!res.ok) throw new Error(await res.text().catch(() => `HTTP ${res.status}`)); ... } catch (e) { msg.textContent = 'Failed to save: ' + e.message; }

Prevention

When it happens

Trigger: POST /api/auth/settings returns 4xx (unauthenticated, admin-only endpoint, invalid model/quality value) or 5xx; network failure; auto-save fires on 'change' events while a previous save is in flight.

Common situations: Non-admin user opening the settings pane; auth cookie expired so the save silently 401s; choosing a model the backend rejects; rapid consecutive changes racing each other.

Related errors


AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14). Data as JSON: /api/errors/b53692c7464bb8a0. Report an issue: GitHub.