n8n-io/n8n · error · NodeOperationError
Parameter ${parameter.name} is not a valid JSON: ${error.mes
Error message
Parameter ${parameter.name} is not a valid JSON: ${error.message} What it means
Thrown by configureToolFunction when a tool parameter of type 'json' receives a string argument (not already an object) that fails JSON.parse. This is distinct from the raw (qsRaw/headersRaw/bodyRaw) placeholders; it applies to individually-typed json parameters.
Source
Thrown at packages/@n8n/nodes-langchain/nodes/tools/ToolHttpRequest/utils.ts:771
`Model did not provide parameter '${parameter.name}' which is required and must be present in the input`,
{ itemIndex },
);
}
}
for (const parameter of toolParameters) {
let argument = dataFromModel[parameter.name];
if (
argument &&
parameter.type === 'json' &&
!['qsRaw', 'headersRaw', 'bodyRaw'].includes(parameter.key ?? '') &&
typeof argument !== 'object'
) {
try {
argument = jsonParse(String(argument));
} catch (error) {
throw new NodeOperationError(
ctx.getNode(),
`Parameter ${parameter.name} is not a valid JSON: ${error.message}`,
{
itemIndex,
},
);
}
}
if (parameter.sendIn === 'path') {
argument = String(argument);
//remove " or ' from start or end
argument = argument.replace(/^['"]+|['"]+$/g, '');
options.url = options.url.replace(`{${parameter.name}}`, argument);
continue;
}View on GitHub (pinned to 5ac6606e81)
Solutions
- Clarify in the parameter description that the value must be a valid JSON object string.
- Change the parameter type to 'string' and parse it downstream in the sub-workflow.
- Simplify the JSON shape the model must produce.
- Use the structured-tool schema path so the framework coerces the value.
Example fix
// before: parameter type 'json', model sends '{ name: "x" }' (unquoted keys) → throws
// after: parameter type 'string', then parse in the workflow
{ name: 'filter', type: 'string' }
// in sub-workflow: JSON.parse($json.filter) Defensive patterns
Strategy: try-catch
Validate before calling
if (parameter.type === 'json' && typeof argument === 'string') {
try { argument = JSON.parse(argument); }
catch { argument = { value: argument }; /* graceful wrap */ }
} Type guard
function looksLikeJson(v: string): boolean {
const t = v.trim(); return (t.startsWith('{') && t.endsWith('}')) || (t.startsWith('[') && t.endsWith(']'));
} Try / catch
try { argument = jsonParse(String(argument)); }
catch (e) { /* degrade to string param or re-prompt */ } Prevention
- Prefer parameter type 'string' over 'json' unless structured data is required.
- Document the expected JSON shape explicitly in the parameter description.
- Let the structured-tool framework coerce JSON arguments.
When it happens
Trigger: The model supplies a malformed JSON string for a parameter declared as type 'json' (e.g. unquoted keys, single quotes, trailing comma); the model sends a plain string where a JSON object was expected.
Common situations: Complex nested JSON parameters that confuse the model; models that wrap JSON in backticks or prose; type set to 'json' but the model treats it as free text.
Related errors
- Input is not a valid JSON: ${error.message}
- Model did not provide parameter '${parameter.name}' which is
- The response type must be an object or an array of objects
- Could not replace placeholders in ${key}: ${error.message}
- Failed to parse ${label} at ${path}: ${msg}
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/706844ad2ba0a3b2.
Report an issue: GitHub.