Error Handling
Ack provides detailed error information when validation fails. This guide explains how to interpret and use these errors.
The SchemaResult Object
All safeParse() methods in Ack return a SchemaResult object. This object encapsulates either the successfully validated data or a SchemaError.
result.isOk: Returnstrueif validation succeeded,falseotherwise.result.isFail: Returnstrueif validation failed,falseotherwise.result.getOrThrow(): Returns the validated data ifisOkis true, otherwise throws an exception.result.getOrNull(): Returns the validated data ifisOkis true, otherwise returnsnull.result.getError(): Returns theSchemaErrorifisFailis true, otherwise throws an exception.result.getOrElse(defaultValue): Returns the validated data ifisOkis true, otherwise returns thedefaultValue.
import 'package:ack/ack.dart';
final schema = Ack.string().minLength(5);
final result = schema.safeParse('abc');
if (result.isFail) {
final error = result.getError();
print('Validation failed: $error');
// Try to get data (will throw)
try {
result.getOrThrow();
} catch (e) {
print('Caught exception: $e');
}
// Get a default value
final dataOrDefault = result.getOrElse(() => 'default_string');
print('Data or default: $dataOrDefault'); // Output: default_string
}
Understanding SchemaError
The SchemaError object contains details about the validation failure.
error.name: A short identifier for the error type (e.g.,'string','object').error.errorKey: The specific error key (e.g.,'schema_constraints_error','schema_nested_error').error.value: The actual value that failed validation.error.schema: The schema that was being validated against.
final userSchema = Ack.object({
'name': Ack.string(),
'age': Ack.integer().min(18),
'address': Ack.object({
'city': Ack.string()
})
});
final invalidData = {
'name': 'Test',
'age': 15, // Fails min(18)
'address': {
'city': 123 // Fails Ack.string
}
};
final result = userSchema.safeParse(invalidData);
if (result.isFail) {
final error = result.getError();
print('Error Name: ${error.name}'); // Example: 'object'
print('Error Key: ${error.errorKey}'); // Example: 'schema_nested_error'
print('Failed Value: ${error.value}'); // Example: the invalid data
print('Full Error: $error'); // Complete error details
// Note: The exact error structure (especially for nested errors) can vary.
// Sometimes the top-level error might be SchemaNestedError,
// and you might need to inspect its nested errors.
}
Error Types
Ack uses specific error types that inherit from SchemaError. Each error type provides detailed information about why validation failed.
TypeMismatchError
Occurs when the input value type doesn't match the expected schema type.
final schema = Ack.string();
final result = schema.safeParse(42); // Number instead of string
if (result.isFail) {
final error = result.getError() as TypeMismatchError;
print('Expected: ${error.expectedType}'); // "string"
print('Actual: ${error.actualType}'); // "integer"
print('Error: ${error.message}'); // "Expected string, got integer"
}
SchemaConstraintsError
Occurs when the value violates one or more validation constraints (e.g., minLength, min, email).
final schema = Ack.string().minLength(5).email();
final result = schema.safeParse('abc');
if (result.isFail) {
final error = result.getError() as SchemaConstraintsError;
print('Constraint violations: ${error.constraints.length}');
// Access individual failed constraints
for (final constraintError in error.constraints) {
print('- Constraint: ${constraintError.constraint}');
print('- Message: ${constraintError.message}');
}
}
SchemaNestedError
Occurs when validation fails within nested objects or lists. Contains a list of child errors.
final schema = Ack.object({
'name': Ack.string().minLength(2),
'age': Ack.integer().min(0),
});
final result = schema.safeParse({
'name': 'J', // Too short
'age': -5, // Negative
});
if (result.isFail) {
final error = result.getError() as SchemaNestedError;
print('Nested errors: ${error.errors.length}');
// Recursively inspect nested errors
for (final nestedError in error.errors) {
print('- Field: ${nestedError.name}');
print('- Error: ${nestedError.message}');
}
}
SchemaValidationError
Occurs when custom validation logic added via .refine() fails.
final schema = Ack.integer().refine(
(value) => value % 2 == 0,
message: 'Must be an even number',
);
final result = schema.safeParse(3);
if (result.isFail) {
final error = result.getError() as SchemaValidationError;
print('Validation error: ${error.message}'); // "Must be an even number"
}
SchemaTransformError
Occurs when a transformation function (from .transform()) throws an exception.
final schema = Ack.string().transform((value) {
if (value == null) throw Exception('Cannot transform null');
return value.toUpperCase();
});
final result = schema.safeParse(null);
if (result.isFail) {
final error = result.getError() as SchemaTransformError;
print('Transform error: ${error.message}');
print('Cause: ${error.cause}'); // Original exception
}
Working with Error Types
Use pattern matching or type checks to handle different error types:
final result = schema.safeParse(data);
if (result.isFail) {
final error = result.getError();
switch (error) {
case TypeMismatchError():
print('Wrong type: expected ${error.expectedType}');
case SchemaConstraintsError():
print('Failed ${error.constraints.length} constraints');
case SchemaNestedError():
print('Nested validation failed at ${error.errors.length} locations');
case SchemaValidationError():
print('Custom validation failed: ${error.message}');
case SchemaTransformError():
print('Transformation failed: ${error.cause}');
default:
print('Validation failed: ${error.message}');
}
}
Displaying Errors in UI (Flutter Example)
When using Ack with Flutter forms, you can extract the error message for display.
// Inside TextFormField validator
validator: (value) {
final result = someSchema.safeParse(value);
if (result.isFail) {
// Return the error details for the UI
return result.getError().toString();
}
return null; // Return null if valid
}
See the Form Validation Guide for more details.
Custom Error Messages
Built-in constraints provide default error messages. For custom error messages, create custom constraints using the .constrain() method. See Custom Validation Guide for details.
// Built-in constraints use default messages
final schema = Ack.string().minLength(5);
final result = schema.safeParse('abc');
if (result.isFail) {
final error = result.getError();
print(error.toString()); // Output: validation error details
}
Next Steps
Learn more about related topics:
- Custom Validation: Create custom constraints with tailored error messages
- Flutter Forms: Display validation errors in Flutter form widgets
- Validation Rules: Explore all built-in validation constraints
- Schema Types: Learn about different schema types and their behavior
- Common Recipes: See practical error handling patterns