Skip to content

Commit 6befb91

Browse files
update validation error messaging
1 parent c19c0e1 commit 6befb91

File tree

3 files changed

+89
-9
lines changed

3 files changed

+89
-9
lines changed

redisvl/exceptions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ class SchemaValidationError(RedisVLError):
2727
"""Error when validating data against a schema."""
2828

2929
def __init__(self, message, index=None):
30-
if index is not None:
30+
# Only add index prefix if the message doesn't already contain detailed validation info
31+
if index is not None and not message.startswith("Schema validation failed"):
3132
message = f"Validation failed for object at index {index}: {message}"
3233
super().__init__(message)
3334

redisvl/index/index.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -779,9 +779,9 @@ def load(
779779
batch_size=batch_size,
780780
validate=self._validate_on_load,
781781
)
782-
except SchemaValidationError:
783-
# Pass through validation errors directly
784-
logger.exception("Schema validation error while loading data")
782+
except SchemaValidationError as e:
783+
# Log the detailed validation error with actionable information
784+
logger.error("Data validation failed during load operation")
785785
raise
786786
except Exception as e:
787787
# Wrap other errors as general RedisVL errors
@@ -1573,9 +1573,9 @@ def add_field(d):
15731573
batch_size=batch_size,
15741574
validate=self._validate_on_load,
15751575
)
1576-
except SchemaValidationError:
1577-
# Pass through validation errors directly
1578-
logger.exception("Schema validation error while loading data")
1576+
except SchemaValidationError as e:
1577+
# Log the detailed validation error with actionable information
1578+
logger.error("Data validation failed during load operation")
15791579
raise
15801580
except Exception as e:
15811581
# Wrap other errors as general RedisVL errors

redisvl/index/storage.py

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
IndexType,
3030
)
3131

32+
import json
33+
3234
from redisvl.exceptions import SchemaValidationError
3335
from redisvl.redis.utils import convert_bytes
3436
from redisvl.schema import IndexSchema
@@ -200,6 +202,80 @@ def _get_keys(
200202
generated_keys.append(key)
201203
return generated_keys
202204

205+
def _create_readable_validation_error_message(
206+
self, validation_error: ValidationError, obj_index: int, obj: Dict[str, Any]
207+
) -> str:
208+
"""
209+
Create a human-readable error message from a Pydantic ValidationError.
210+
211+
Args:
212+
validation_error: The Pydantic ValidationError
213+
obj_index: The index of the object that failed validation
214+
obj: The object that failed validation
215+
216+
Returns:
217+
A detailed, actionable error message
218+
"""
219+
error_details = []
220+
221+
for error in validation_error.errors():
222+
field_name = ".".join(str(loc) for loc in error["loc"])
223+
error_type = error["type"]
224+
error_msg = error["msg"]
225+
input_value = error.get("input", "N/A")
226+
227+
# Create a more descriptive error message based on error type
228+
if error_type == "bytes_type":
229+
if isinstance(input_value, bool):
230+
suggestion = (
231+
f"Field '{field_name}' expects bytes (vector data), but got boolean value '{input_value}'. "
232+
f"If this should be a vector field, provide a list of numbers or bytes. "
233+
f"If this should be a different field type, check your schema definition."
234+
)
235+
else:
236+
suggestion = (
237+
f"Field '{field_name}' expects bytes (vector data), but got {type(input_value).__name__} value '{input_value}'. "
238+
f"For vector fields, provide a list of numbers or bytes."
239+
)
240+
elif error_type == "bool_type":
241+
suggestion = (
242+
f"Field '{field_name}' cannot be boolean. Got '{input_value}' of type {type(input_value).__name__}. "
243+
f"Provide a valid numeric value instead."
244+
)
245+
elif error_type == "string_type":
246+
suggestion = (
247+
f"Field '{field_name}' expects a string, but got {type(input_value).__name__} value '{input_value}'. "
248+
f"Convert the value to a string or check your data types."
249+
)
250+
elif error_type == "list_type":
251+
suggestion = (
252+
f"Field '{field_name}' expects a list (for vector data), but got {type(input_value).__name__} value '{input_value}'. "
253+
f"Provide the vector as a list of numbers."
254+
)
255+
elif "dimensions" in error_msg.lower():
256+
suggestion = (
257+
f"Vector field '{field_name}' has incorrect dimensions. {error_msg}"
258+
)
259+
elif "range" in error_msg.lower():
260+
suggestion = f"Vector field '{field_name}' has values outside the allowed range. {error_msg}"
261+
else:
262+
suggestion = f"Field '{field_name}': {error_msg}"
263+
264+
error_details.append(f" • {suggestion}")
265+
266+
# Create the final error message
267+
if len(error_details) == 1:
268+
detail_msg = error_details[0].strip(" • ")
269+
else:
270+
detail_msg = "Multiple validation errors:\n" + "\n".join(error_details)
271+
272+
return (
273+
f"Schema validation failed for object at index {obj_index}. {detail_msg}\n"
274+
f"Object data: {json.dumps(obj, default=str, indent=2)[:200]}{'...' if len(str(obj)) > 200 else ''}\n"
275+
f"Hint: Check that your data types match the schema field definitions. "
276+
f"Use index.schema.fields to view expected field types."
277+
)
278+
203279
def _preprocess_and_validate_objects(
204280
self,
205281
objects: Iterable[Any],
@@ -248,8 +324,11 @@ def _preprocess_and_validate_objects(
248324
prepared_objects.append((key, processed_obj))
249325

250326
except ValidationError as e:
251-
# Convert Pydantic ValidationError to SchemaValidationError with index context
252-
raise SchemaValidationError(str(e), index=i) from e
327+
# Create detailed, readable error message
328+
detailed_message = self._create_readable_validation_error_message(
329+
e, i, obj
330+
)
331+
raise SchemaValidationError(detailed_message) from e
253332
except Exception as e:
254333
# Capture other exceptions with context
255334
object_id = f"at index {i}"

0 commit comments

Comments
 (0)