jumpserver/jumpserver · error · ValidationError
Expected {expected}.
Error message
Expected {expected}. What it means
ValidationError raised when a scalar's Python type does not match any of the schema's declared types (with special handling: booleans are not accepted as integers/numbers, and numeric strings are not coerced). The message echoes the expected type(s).
Source
Thrown at apps/chat_ai/executor/request_builder.py:25
def _validate_scalar(value, schema, location):
expected = schema.get('type')
nullable = schema.get('nullable') or 'null' in (schema.get('type') if isinstance(schema.get('type'), list) else [])
if value is None:
if nullable or not expected:
return
raise ValidationError({location: 'This value may not be null.'})
expected_types = expected if isinstance(expected, list) else [expected]
def matches(item):
if item == 'integer':
return isinstance(value, int) and not isinstance(value, bool)
if item == 'number':
return isinstance(value, (int, float)) and not isinstance(value, bool)
type_map = {'string': str, 'boolean': bool, 'array': list, 'object': dict}
return item in type_map and isinstance(value, type_map[item])
if expected and not any(matches(item) for item in expected_types):
raise ValidationError({location: f'Expected {expected}.'})
if schema.get('enum') and value not in schema['enum']:
raise ValidationError({location: f'Value must be one of {schema["enum"]}.'})
if isinstance(value, str):
if schema.get('minLength') is not None and len(value) < schema['minLength']:
raise ValidationError({location: f'Minimum length is {schema["minLength"]}.'})
if schema.get('maxLength') is not None and len(value) > schema['maxLength']:
raise ValidationError({location: f'Maximum length is {schema["maxLength"]}.'})
if schema.get('pattern') and not re.search(schema['pattern'], value):
raise ValidationError({location: 'Value does not match the required pattern.'})
if isinstance(value, (int, float)) and not isinstance(value, bool):
if schema.get('minimum') is not None and value < schema['minimum']:
raise ValidationError({location: f'Minimum value is {schema["minimum"]}.'})
if schema.get('maximum') is not None and value > schema['maximum']:
raise ValidationError({location: f'Maximum value is {schema["maximum"]}.'})
def validate_json(value, schema, location='body'):
if not schema:View on GitHub (pinned to 6ec464fabd)
Solutions
- Coerce arguments to the schema-declared types before calling build/execute (int(x) for integer fields, etc.)
- Align the tool schema advertised to the agent with the Core API schema so the model emits correct types
- Validate arguments against the schema and retry with a corrective prompt on type errors
- Watch the bool special case: booleans fail integer/number checks by design
Example fix
# before
arguments = {'body': {'count': '10', 'verbose': 'true'}}
# after
arguments = {'body': {'count': int('10'), 'verbose': True}} Defensive patterns
Strategy: validation
Validate before calling
function coerce(value, schema) {
if (schema.type === 'integer' || schema.type === 'number') return Number(value);
if (schema.type === 'boolean') return Boolean(value);
return value;
}
args.body = mapSchema(args.body, bodySchema, coerce); Type guard
const matchesType = (v: unknown, t: string): boolean => t === 'integer' ? (typeof v === 'number' && Number.isInteger(v)) : t === 'number' ? typeof v === 'number' : t === 'string' ? typeof v === 'string' : t === 'boolean' ? typeof v === 'boolean' : t === 'array' ? Array.isArray(v) : t === 'object' ? typeof v === 'object' && v !== null && !Array.isArray(v) : false;
Try / catch
try {
await executor.execute(opId, args, ctx, { agentRun: run });
} catch (e) {
if (e instanceof ValidationError && /Expected /.test(JSON.stringify(e.detail))) {
args = coerceToSchema(args, schema);
return await executor.execute(opId, args, ctx, { agentRun: run });
}
throw e;
} Prevention
- Coerce numeric/boolean inputs before calling the API
- Keep advertised tool schemas identical to Core API schemas
- Remember booleans are rejected for integer/number fields by design
When it happens
Trigger: Passing '5' (string) where {'type': 'integer'} is expected, true where string is expected, or 1.0 passed as an int-only field; schema declaring a list of allowed types with the value matching none.
Common situations: LLM tool-call arguments arriving as strings from JSON, frontend form inputs unconverted, schema tightened from ['integer','string'] to 'integer'.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- This value may not be null.
- Value must be one of {schema["enum"]}.
- Maximum item count is {schema["maxItems"]}.
- Must be an object.
- path_params and query_params must be objects.
AI-assisted analysis of jumpserver/jumpserver@6ec464fabd (2026-08-28).
Data as JSON: /api/errors/a694695f1bc72fee.
Report an issue: GitHub.