linshenkx/prompt-optimizer · error · ContextError

CONTEXT_ERROR_CODES.IMPORT_FORMAT_ERROR

CONTEXT_ERROR_CODES.IMPORT_FORMAT_ERROR

Error message

Invalid context bundle format

What it means

extractVariable validates the selection indices before substitution: startIndex must be >= 0, endIndex must not exceed messageContent.length, and startIndex must be strictly less than endIndex. Any violation throws 'Invalid selection range'. This guards substring() from producing wrong results.

Source

Thrown at packages/core/src/services/context/repo.ts:441

      return doc;
    });
  }

  async exportAll(): Promise<ContextBundle> {
    const doc = await this.getStoreDoc();
    
    return {
      type: 'context-bundle',
      version: CONTEXT_STORE_VERSION,
      currentId: doc.currentId,
      contexts: Object.values(doc.contexts)
    };
  }

  async importAll(bundle: ContextBundle, mode: ImportMode): Promise<ImportResult> {
    // 验证bundle格式
    if (!bundle || bundle.type !== 'context-bundle' || !Array.isArray(bundle.contexts)) {
      throw new ContextError(CONTEXT_ERROR_CODES.IMPORT_FORMAT_ERROR, 'Invalid context bundle format');
    }

    if (bundle.contexts.length === 0) {
      throw new ContextError(CONTEXT_ERROR_CODES.IMPORT_FORMAT_ERROR, 'Context bundle must contain at least one context');
    }

    let imported = 0;
    let skipped = 0;
    let predefinedVariablesRemoved = 0;
    const idMapping: Record<string, string> = {};

    await this.updateStoreDoc(doc => {
      const now = getCurrentISOTime();

      switch (mode) {
        case 'replace':
          // 替换模式:清空现有数据
          doc.contexts = {};

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. Recompute indices against the current messageContent right before calling extractVariable
  2. Disable the extract button for empty selections (start === end)
  3. Clamp/validate indices in the UI layer with the same rules before invoking the service

Example fix

// before
const r = extractor.extractVariable(name, content, selected, selectionStart, selectionEnd)

// after
if (selectionStart < 0 || selectionEnd > content.length || selectionStart >= selectionEnd) {
  throw new Error('Invalid selection range')
}
const r = extractor.extractVariable(name, content, content.slice(selectionStart, selectionEnd), selectionStart, selectionEnd)
Defensive patterns

Strategy: validation

Validate before calling

function isValidRange(content: string, start: number, end: number): boolean {
  return start >= 0 && end <= content.length && start < end
}
if (!isValidRange(messageContent, startIndex, endIndex)) {
  throw new Error('Selection is empty or out of bounds')
}

Type guard

type ValidRange = { start: number; end: number }
function isValidRange(r: { start: number; end: number }, len: number): r is ValidRange {
  return r.start >= 0 && r.end <= len && r.start < r.end
}

Try / catch

try {
  const r = extractor.extractVariable(name, content, selectedText, start, end)
} catch (error) {
  if (error instanceof Error && error.message === 'Invalid selection range') {
    // recompute selection from the live editor and retry once
    return reselectAndRetry()
  }
  throw error
}

Prevention

When it happens

Trigger: Calling extractVariable with startIndex < 0, endIndex > message length, startIndex >= endIndex, or indices computed against a different (stale/edited) version of messageContent.

Common situations: User edits the message after selection indices were captured, shifting offsets; off-by-one when computing endIndex; empty selection (start === end) submitted; stale state after undo/redo.

Related errors


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