linshenkx/prompt-optimizer · error · VariableExtractionParseError
variables[${index}] is missing a valid "reason" field.
Error message
variables[${index}] is missing a valid "reason" field. What it means
Each extracted variable must carry a human-readable reason string explaining why it was chosen as a variable. normalizeExtractionResponse throws this when variables[i].reason is missing or not a string, since the reason is part of the service's return contract.
Source
Thrown at packages/core/src/services/variable-extraction/service.ts:239
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.`);
}
return {
name: variable.name.trim(),
value: variable.value,
position: {
originalText: variable.position.originalText,
occurrence: variable.position.occurrence,
},
reason: variable.reason,
category: variable.category ? String(variable.category) : undefined,
};
});
return {
variables,
summary: data.summary.trim(),
};View on GitHub (pinned to 3e677b1d9f)
Solutions
- Update the extraction template so every variable object explicitly includes a 'reason' string
- Default-fill reason when pre-processing the response if it's unimportant to your flow
- Verify the template 'variable-extraction' content in your template manager matches the expected schema
- Increase max_tokens if responses are being truncated mid-object
Example fix
// before
await service.parseExtractionResult(text);
// after
const parsed = JSON.parse(text);
for (const v of parsed.variables ?? []) {
if (typeof v.reason !== 'string') v.reason = 'auto-filled: extracted by model';
}
await service.parseExtractionResult(JSON.stringify(parsed)); Defensive patterns
Strategy: validation
Validate before calling
for (const v of parsed.variables ?? []) { if (typeof v.reason !== 'string') v.reason = ''; } Type guard
const hasReason = (v: any) => typeof v?.reason === 'string';
Try / catch
catch (e) { if (e instanceof VariableExtractionParseError && e.message.includes('reason')) { /* default-fill and re-parse */ } throw e; } Prevention
- Require a short reason string per variable in the template
- Treat optional-looking fields as mandatory in the prompt wording
When it happens
Trigger: variables[i] has no 'reason' key, or reason is a number/object/null (e.g. reason: 5 or reason: {"why": "..."}).
Common situations: Prompt template that never asked for a reason field; model abbreviates the response and drops optional-looking fields; older template versions with a different schema; max_tokens truncation cutting off trailing fields.
Related errors
- variables[${index}] is missing a valid "position" object.
- variables[${index}].position is missing a valid "originalTex
- variables[${index}].position is missing a valid "occurrence"
- Generation result is not a valid object.
- Generation result must have a "values" array.
AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27).
Data as JSON: /api/errors/ec9b12172f7c7c89.
Report an issue: GitHub.