linshenkx/prompt-optimizer · error · VariableExtractionParseError

variables[${index}] is missing a valid "position" object.

Error message

variables[${index}] is missing a valid "position" object.

What it means

Thrown by normalizeExtractionResponse in the variable-extraction service when a variable in the LLM's extraction response is missing its position object or position is not an object. The service strictly validates the LLM's JSON output shape before returning it, because position data (originalText + occurrence) is required to locate the variable inside the prompt. Any deviation from the expected schema raises VariableExtractionParseError.

Source

Thrown at packages/core/src/services/variable-extraction/service.ts:223

    }

    // 标准化每个变量
    const variables: ExtractedVariable[] = data.variables.map((variable: any, index: number) => {
      // 验证必需字段
      if (!variable || typeof variable !== 'object') {
        throw new VariableExtractionParseError(`variables[${index}] is not a valid object.`);
      }

      if (typeof variable.name !== 'string' || !variable.name.trim()) {
        throw new VariableExtractionParseError(`variables[${index}] is missing a valid "name" field.`);
      }

      if (typeof variable.value !== 'string') {
        throw new VariableExtractionParseError(`variables[${index}] is missing a valid "value" field.`);
      }

      if (!variable.position || typeof variable.position !== 'object') {
        throw new VariableExtractionParseError(`variables[${index}] is missing a valid "position" object.`);
      }

      if (typeof variable.position.originalText !== 'string') {
        throw new VariableExtractionParseError(
          `variables[${index}].position is missing a valid "originalText" field.`
        );
      }

      if (typeof variable.position.occurrence !== 'number') {
        throw new VariableExtractionParseError(
          `variables[${index}].position is missing a valid "occurrence" number.`
        );
      }

      if (typeof variable.reason !== 'string') {
        throw new VariableExtractionParseError(`variables[${index}] is missing a valid "reason" field.`);
      }

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. Inspect the raw LLM response logged before normalization to see what shape 'position' actually has
  2. Tighten the extraction prompt/template to explicitly require {"position": {"originalText": "...", "occurrence": N}} for every variable
  3. Use a stronger model or lower temperature so the JSON schema is followed more reliably
  4. Catch VariableExtractionParseError and retry generation once before failing
  5. If you control the response, pre-validate/repair the payload before passing it to parseExtractionResult

Example fix

// before
const result = await extractionService.parseExtractionResult(rawLlmText);

// after
const parsed = JSON.parse(rawLlmText);
for (const v of parsed.variables ?? []) {
  if (!v.position || typeof v.position !== 'object') {
    throw new Error(`missing position for variable ${v.name}`); // or repair: v.position = { originalText: v.value, occurrence: 0 }
  }
}
const result = await extractionService.parseExtractionResult(rawLlmText);
Defensive patterns

Strategy: type-guard

Validate before calling

const ok = (parsed.variables ?? []).every(v => v.position && typeof v.position === 'object' && !Array.isArray(v.position));

Type guard

function hasValidPosition(v: any): v is { name: string; position: Record<string, unknown> } {
  return !!v && typeof v === 'object' && !!v.position && typeof v.position === 'object' && !Array.isArray(v.position);
}

Try / catch

try { const r = service.parseExtractionResult(text); } catch (e) { if (e instanceof VariableExtractionParseError && /position/.test(e.message)) { /* re-prompt or repair */ } else throw e; }

Prevention

When it happens

Trigger: Calling parseExtractionResult with an LLM response where variables[i] has no 'position' key, position is null/undefined, or position is a string/number instead of an object (e.g. the model returned "position": "paragraph 2").

Common situations: Weaker LLM models omitting nested objects; prompt template drift after a version upgrade changing the output schema; the model wrapping position differently (e.g. position: { location: {...} }); truncated JSON from max_tokens limits.

Related errors


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