{"record":{"id":"605f41479ad88ca2","repo":"linshenkx/prompt-optimizer","slug":"extraction-result-must-have-a-variables-array","errorCode":null,"errorMessage":"Extraction result must have a \"variables\" array.","messagePattern":"Extraction result must have a \"variables\" array\\.","errorType":"validation","errorClass":"VariableExtractionParseError","httpStatus":null,"severity":"error","filePath":"packages/core/src/services/variable-extraction/service.ts","lineNumber":199,"sourceCode":"      } catch (fallbackError) {\n        throw new VariableExtractionParseError(\n          `Failed to parse LLM response: ${error instanceof Error ? error.message : String(error)}. Raw content length: ${content.length} characters.`\n        );\n      }\n    }\n  }\n\n  /**\n   * 标准化提取响应（统一结构）\n   */\n  private normalizeExtractionResponse(data: any): VariableExtractionResponse {\n    if (!data || typeof data !== 'object') {\n      throw new VariableExtractionParseError('Extraction result is not a valid object.');\n    }\n\n    // 验证 variables 字段\n    if (!Array.isArray(data.variables)) {\n      throw new VariableExtractionParseError('Extraction result must have a \"variables\" array.');\n    }\n\n    // 验证 summary 字段\n    if (typeof data.summary !== 'string') {\n      throw new VariableExtractionParseError('Extraction result must have a \"summary\" string.');\n    }\n\n    // 标准化每个变量\n    const variables: ExtractedVariable[] = data.variables.map((variable: any, index: number) => {\n      // 验证必需字段\n      if (!variable || typeof variable !== 'object') {\n        throw new VariableExtractionParseError(`variables[${index}] is not a valid object.`);\n      }\n\n      if (typeof variable.name !== 'string' || !variable.name.trim()) {\n        throw new VariableExtractionParseError(`variables[${index}] is missing a valid \"name\" field.`);\n      }\n","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/core/src/services/variable-extraction/service.ts#L181-L217","documentation":"The parsed LLM response is an object, but it lacks a 'variables' array (the field is missing, or is not an Array). 'variables' is a required field of the unified extraction response, so normalization fails before any per-variable validation runs.","triggerScenarios":"Model returns an object whose variables field is omitted, an object instead of an array (e.g. a keyed map of variables), or a string. Reached via extract() when the model's JSON deviates from the required {variables: [], summary: \"\"} shape.","commonSituations":"Model returns {\"extracted\": [...]} or {\"result\": {\"variables\": [...]}} (extra nesting); model returns variables as an object keyed by name; prompt template edited so the field name changed; model omits the field when it finds no variables instead of returning an empty array.","solutions":["Update the prompt/template to state that the output MUST include \"variables\": [] (empty array when nothing is extracted).","Log the parsed object keys to see what field name the model used instead.","Add a pre-normalization shim mapping the actual field (e.g. data.extracted or Object.values(data.variables)) to data.variables.","Try a stronger model or few-shot example showing the exact schema."],"exampleFix":"// before\nreturn this.normalizeExtractionResponse(parsed);\n\n// after\nif (!Array.isArray(parsed.variables) && Array.isArray(parsed.extracted)) parsed.variables = parsed.extracted;\nreturn this.normalizeExtractionResponse(parsed);","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"const hasVariablesArray = (d: unknown): d is { variables: unknown[]; [k: string]: unknown } =>\n  isExtractionObject(d) && Array.isArray((d as any).variables);","tryCatchPattern":"try {\n  await extractionService.extract({ modelKey, content });\n} catch (e) {\n  if (e instanceof VariableExtractionParseError && /\"variables\" array/.test(e.message)) {\n    // remap the actual field name (e.g. extracted) and retry once\n  }\n  throw e;\n}","preventionTips":["State explicitly in the prompt that the output must contain a top-level \"variables\" array (empty array if none).","Normalize alternate field names (extracted, result, items) in your own pre-processing layer.","Use structured output / JSON schema enforcement if the model provider supports it."],"tags":["llm","json","schema","validation"],"backgroundTag":"llm-response-schema-mismatch","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}