linshenkx/prompt-optimizer · error · VariableExtractionParseError

Extraction result is not a valid object.

Error message

Extraction result is not a valid object.

What it means

The LLM response was parsed to a value, but that value is not an object (null, array, string, number, or boolean). The extraction contract requires a top-level JSON object with variables and summary, so normalization aborts immediately.

Source

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

      // 尝试直接解析(不通过 jsonrepair)
      try {
        const parsed = JSON.parse(jsonText);
        return this.normalizeExtractionResponse(parsed);
      } catch (fallbackError) {
        throw new VariableExtractionParseError(
          `Failed to parse LLM response: ${error instanceof Error ? error.message : String(error)}. Raw content length: ${content.length} characters.`
        );
      }
    }
  }

  /**
   * 标准化提取响应(统一结构)
   */
  private normalizeExtractionResponse(data: any): VariableExtractionResponse {
    if (!data || typeof data !== 'object') {
      throw new VariableExtractionParseError('Extraction result is not a valid object.');
    }

    // 验证 variables 字段
    if (!Array.isArray(data.variables)) {
      throw new VariableExtractionParseError('Extraction result must have a "variables" array.');
    }

    // 验证 summary 字段
    if (typeof data.summary !== 'string') {
      throw new VariableExtractionParseError('Extraction result must have a "summary" string.');
    }

    // 标准化每个变量
    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.`);
      }

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. Fix the prompt/template to explicitly require an object like {"variables": [...], "summary": "..."}.
  2. Log the parsed value (typeof + preview) to see which non-object shape the model emits.
  3. If the model consistently returns an array, add a shim that wraps it: Array.isArray(parsed) ? { variables: parsed } : parsed.
  4. Use a stronger model with better instruction-following for extraction.

Example fix

// before
return this.normalizeExtractionResponse(parsed);

// after
return this.normalizeExtractionResponse(Array.isArray(parsed) ? { variables: parsed, summary: '' } : parsed);
Defensive patterns

Strategy: type-guard

Type guard

const isExtractionObject = (d: unknown): d is Record<string, unknown> =>
  !!d && typeof d === 'object' && !Array.isArray(d);

Try / catch

try {
  await extractionService.extract({ modelKey, content });
} catch (e) {
  if (e instanceof VariableExtractionParseError && /not a valid object/.test(e.message)) {
    // model returned array/primitive: fix prompt schema or wrap arrays
  }
  throw e;
}

Prevention

When it happens

Trigger: Model returns a bare JSON array of variables, a quoted string, a number, or literal null instead of an object. Reached via extract() whenever parseExtractionResult succeeds on a non-object JSON payload.

Common situations: Prompt asks for 'a list of variables' so the model returns [...] instead of {"variables": [...]}; model returns the string 'null' or an empty response coerced to null; template output-format instruction drifted from the unified schema.

Related errors


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