linshenkx/prompt-optimizer · error · Error

Invalid edit session

Error message

Invalid edit session

What it means

updateExistingModel throws 'Invalid edit session' when form.value.originalId is falsy. The form was routed into the update path (editingModelId set) but the form state never captured the id of the model being edited, so there is nothing to update.

Source

Thrown at packages/ui/src/composables/model/useTextModelManager.ts:798

      isLoadingModelOptions.value = false
    }
  }

  const resolveFormMetadata = (
    providerId: string,
    modelId: string,
    existingConfig?: TextModelConfig
  ) => resolveTextModelMetadata({
    providerId,
    modelId,
    registry: textAdapterRegistry,
    existingProviderMeta: existingConfig?.providerMeta,
    existingModelMeta: existingConfig?.modelMeta
  })

  const updateExistingModel = async () => {
    if (!form.value.originalId) {
      throw new Error('Invalid edit session')
    }

    const existingConfig = await modelManager.getModel(form.value.originalId)
    if (!existingConfig) {
      throw new Error('Model not found')
    }

    const connectionConfig: TextConnectionConfig = {
      baseURL: (form.value.connectionConfig.baseURL as string)?.trim() || existingConfig.connectionConfig?.baseURL,
      ...form.value.connectionConfig
    }

    if (form.value.displayMaskedKey) {
      if (form.value.originalApiKey) {
        connectionConfig.apiKey = form.value.originalApiKey
      } else {
        delete connectionConfig.apiKey
      }

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. When entering edit mode, always set form.value.originalId together with editingModelId
  2. Avoid calling resetFormState() while an edit session is active, or make it clear originalId too and exit edit mode
  3. Before save, assert editingModelId === form.originalId and restart the edit flow if not
  4. If the state is inconsistent, fall back to createNewModel() path or re-open edit via the model id

Example fix

// before
const updateExistingModel = async () => {
  if (!form.value.originalId) throw new Error('Invalid edit session')

// after
const updateExistingModel = async () => {
  if (!form.value.originalId) {
    form.value.originalId = editingModelId.value
  }
  if (!form.value.originalId) throw new Error('Invalid edit session')
Defensive patterns

Strategy: validation

Validate before calling

if (editingModelId.value && !form.value.originalId) {
  form.value.originalId = editingModelId.value
}
if (!form.value.originalId) { /* treat as create, or abort */ }

Type guard

const hasEditSession = (f: { originalId?: string | null }): f is { originalId: string } =>
  typeof f.originalId === 'string' && f.originalId.length > 0

Try / catch

try { await saveForm() } catch (e) { if (String(e?.message) === 'Invalid edit session') { resetFormState(); notify('Edit session expired, please retry') } else throw e }

Prevention

When it happens

Trigger: saveForm() choosing the update branch because editingModelId is set, while form.originalId was cleared by resetFormState() or never set when the edit session started. Can also happen if the form object is replaced wholesale without preserving originalId.

Common situations: Form state reset mid-session (e.g. prepareForClone ran after an edit started); reactivity bug where form.value is reassigned and originalId is dropped; two dialogs sharing the same composable instance clobbering each other's state.


AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27). Data as JSON: /api/errors/e34d3a35d8783269. Report an issue: GitHub.