{"record":{"id":"f386f0eb26b7a798","repo":"mastra-ai/mastra","slug":"could-not-save-the-active-model-pack","errorCode":null,"errorMessage":"Could not save the active model pack","messagePattern":"Could not save the active model pack","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/tui/src/tui/commands/models.ts","lineNumber":93,"sourceCode":"      });\n    }\n    nextSettings.models.activeModelPackId = nextPackId;\n    nextSettings.models.modeDefaults = modeModels;\n  }\n\n  let modeSettingSaved = false;\n  let packSettingSaved = false;\n  let globalSettingsWriteStarted = false;\n  try {\n    await ctx.state.session.thread.setSetting({ key: modeSettingKey, value: modelId });\n    modeSettingSaved = true;\n    const savedModeSetting = await ctx.state.session.thread.getSetting({ key: modeSettingKey });\n    if (savedModeSetting !== modelId) throw new Error(`Could not save the ${modeId} mode model`);\n\n    await ctx.state.session.thread.setSetting({ key: THREAD_ACTIVE_MODEL_PACK_ID_KEY, value: nextPackId });\n    packSettingSaved = true;\n    const savedPackSetting = await ctx.state.session.thread.getSetting({ key: THREAD_ACTIVE_MODEL_PACK_ID_KEY });\n    if (savedPackSetting !== nextPackId) throw new Error('Could not save the active model pack');\n    globalSettingsWriteStarted = true;\n    saveSettings(nextSettings);\n    await ctx.state.session.model.switch({ modelId, scope: 'global' });\n  } catch (error) {\n    if (globalSettingsWriteStarted) {\n      try {\n        saveSettings(settings);\n      } catch {\n        // Keep the original failure. The thread and active model still roll back below.\n      }\n    }\n\n    const rollbacks: Array<Promise<unknown>> = [];\n    if (packSettingSaved) {\n      rollbacks.push(\n        ctx.state.session.thread.setSetting({\n          key: THREAD_ACTIVE_MODEL_PACK_ID_KEY,\n          value: previousPackSetting,","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/tui/src/tui/commands/models.ts#L75-L111","documentation":"When switching the model for a mode, the TUI first persists the new model pack id to thread settings, then reads it back to verify the write actually landed. If the round-trip read does not equal the pack id that was just written, switchCurrentModeModel throws 'Could not save the active model pack'. This is a write-verification failure indicating the settings backend silently dropped or failed to persist the value.","triggerScenarios":"Calling the mode-model switch command when thread.setSetting({ key: THREAD_ACTIVE_MODEL_PACK_ID_KEY, ... }) succeeds without throwing but the subsequent getSetting returns a different value or undefined — e.g. the thread storage adapter silently swallows writes, the thread was closed/recreated mid-switch, or a concurrent write overwrote the key between set and get.","commonSituations":"Storage backend misconfiguration (in-memory or ephemeral store that doesn't persist), corrupted thread state, race with another TUI session writing settings for the same thread, or a custom Thread/Settings implementation whose setSetting doesn't immediately reflect in getSetting.","solutions":["Check that the thread's storage/settings backend persists values synchronously and that getSetting reflects a prior setSetting","Retry the model switch; transient races with another writer resolve on a second attempt","Verify no other TUI session or process is concurrently writing THREAD_ACTIVE_MODEL_PACK_ID_KEY for the same thread","Inspect the thread settings implementation for swallowed errors in setSetting","Clear/recreate the thread state if its settings record is corrupted"],"exampleFix":"// before (custom storage adapter silently ignoring writes)\nasync setSetting({ key, value }) { this.pending[key] = value; }\n// after\nasync setSetting({ key, value }) {\n  this.pending[key] = value;\n  await this.persist();\n  const check = await this.getSetting({ key });\n  if (check !== value) throw new Error(`Failed to persist setting ${key}`);\n}","handlingStrategy":"try-catch","validationCode":"const stored = await ctx.state.session.thread.getSetting({ key: THREAD_ACTIVE_MODEL_PACK_ID_KEY });\nif (stored !== undefined && typeof stored !== 'string') throw new Error('Thread settings backend returned unexpected value');","typeGuard":"function isPersistedSetting(v: unknown): v is string { return typeof v === 'string'; }","tryCatchPattern":"try {\n  await switchCurrentModeModel(ctx, modeId, modelId, packId);\n} catch (error) {\n  if (error instanceof Error && error.message.includes('Could not save')) {\n    // surface a retry / settings-backend diagnostics UI\n  }\n}","preventionTips":["Use a storage adapter whose setSetting is durable and immediately readable","Avoid two TUI sessions writing settings for the same thread concurrently","Add a health check that round-trips a dummy setting at startup","Log the settings backend type alongside this error for diagnosis"],"tags":["persistence","settings","race-condition","storage"],"backgroundTag":"settings-write-verification-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}