0
# Error Handling
1
2
Sophisticated error catching system allowing tests to validate error conditions without stopping compilation, with support for both function and mixin contexts.
3
4
## Capabilities
5
6
### Error Function
7
8
Handles errors in function contexts with optional error catching for testing error states.
9
10
```scss { .api }
11
/**
12
* Error handling function for use inside functions
13
* @param $message - The error message to report
14
* @param $source - Optional source identifier for error context (e.g., function name)
15
* @param $catch - Whether to catch the error and return it as a value instead of throwing
16
* @returns Error message string when $catch is true
17
* @throws Sass @error when $catch is false
18
*/
19
@function error($message, $source: null, $catch: $catch-errors);
20
```
21
22
**Usage Examples:**
23
24
```scss
25
@use 'pkg:sass-true' as *;
26
@use 'sass:meta';
27
28
// In your function code
29
@function divide($a, $b) {
30
@if (meta.type-of($a) != 'number') or (meta.type-of($b) != 'number') {
31
@return error(
32
'$a and $b must both be numbers',
33
'divide()',
34
true // Catch error for testing
35
);
36
}
37
38
@if $b == 0 {
39
@return error(
40
'Cannot divide by zero',
41
'divide()',
42
true
43
);
44
}
45
46
@return math.div($a, $b);
47
}
48
49
// Testing error conditions
50
@include test('Function error handling') {
51
@include assert-equal(
52
divide(10, 0),
53
'ERROR [divide()]: Cannot divide by zero'
54
);
55
56
@include assert-equal(
57
divide('10', 5),
58
'ERROR [divide()]: $a and $b must both be numbers'
59
);
60
61
// Test successful case
62
@include assert-equal(divide(10, 2), 5);
63
}
64
```
65
66
### Error Mixin
67
68
Handles errors in mixin contexts, outputting CSS comments when catching errors.
69
70
```scss { .api }
71
/**
72
* Error handling mixin for use inside mixins and other CSS contexts
73
* @param $message - The error message to report
74
* @param $source - Optional source identifier for error context (e.g., mixin name)
75
* @param $catch - Whether to catch the error and output as CSS comment instead of throwing
76
* @output CSS comment with error details when $catch is true
77
* @throws Sass @error when $catch is false
78
*/
79
@mixin error($message, $source: null, $catch: $catch-errors);
80
```
81
82
**Usage Examples:**
83
84
```scss
85
@use 'pkg:sass-true' as *;
86
87
// In your mixin code
88
@mixin button($type: 'primary', $size: 'medium') {
89
$valid-types: ('primary', 'secondary', 'danger');
90
$valid-sizes: ('small', 'medium', 'large');
91
92
@if not index($valid-types, $type) {
93
@include error(
94
'Invalid button type: #{$type}. Valid types: #{$valid-types}',
95
'button()',
96
true // Catch for testing
97
);
98
} @else if not index($valid-sizes, $size) {
99
@include error(
100
'Invalid button size: #{$size}. Valid sizes: #{$valid-sizes}',
101
'button()',
102
true
103
);
104
} @else {
105
// Generate button styles
106
padding: button-padding($size);
107
background-color: button-color($type);
108
}
109
}
110
111
// Testing mixin error handling
112
@include test('Mixin error handling') {
113
@include assert('Should output error for invalid type') {
114
@include output {
115
@include button('invalid-type');
116
}
117
118
@include contains-string('ERROR [button()]');
119
@include contains-string('Invalid button type: invalid-type');
120
}
121
122
@include assert('Should work correctly with valid inputs') {
123
@include output {
124
@include button('primary', 'large');
125
}
126
127
@include expect {
128
padding: 1rem 2rem;
129
background-color: #007bff;
130
}
131
}
132
}
133
```
134
135
## Configuration
136
137
### Global Error Catching
138
139
Control error behavior globally with the `$catch-errors` setting.
140
141
```scss { .api }
142
/**
143
* Global error catching configuration
144
* @type bool | 'warn'
145
* @default false
146
*/
147
$catch-errors: false !default;
148
```
149
150
**Configuration Examples:**
151
152
```scss
153
@use 'pkg:sass-true' as * with (
154
$catch-errors: true // Catch all errors globally
155
);
156
157
// Or set during testing
158
$catch-errors: 'warn' !global; // Catch errors and show warnings
159
160
@include test('Error behavior with global catching') {
161
// Errors will be caught and returned/output as comments
162
@include assert-equal(
163
problematic-function(),
164
'ERROR: Something went wrong'
165
);
166
}
167
168
// Reset for production
169
$catch-errors: false !global;
170
```
171
172
### Warning Mode
173
174
When `$catch-errors` is set to `'warn'`, errors are caught but also displayed as warnings:
175
176
```scss
177
@use 'pkg:sass-true' as * with (
178
$catch-errors: 'warn'
179
);
180
181
@function test-function() {
182
@return error('This will be caught and warned');
183
}
184
185
// This will output a warning to the console and return the error string
186
$result: test-function();
187
```
188
189
## Advanced Usage
190
191
### Conditional Error Catching
192
193
Override global settings for specific error calls:
194
195
```scss
196
@use 'pkg:sass-true' as *;
197
198
@function strict-function($value) {
199
@if $value == null {
200
// Always throw, never catch (even if $catch-errors is true)
201
@return error('Value cannot be null', 'strict-function()', false);
202
}
203
204
@if $value < 0 {
205
// Conditionally catch for testing
206
@return error('Value must be positive', 'strict-function()', true);
207
}
208
209
@return $value * 2;
210
}
211
```
212
213
### Error Message Formatting
214
215
Error messages follow a consistent format:
216
217
- **With source**: `"ERROR [source]: message"`
218
- **Without source**: `"ERROR: message"`
219
220
```scss
221
@include test('Error message formatting') {
222
@include assert-equal(
223
error('Something failed', 'my-function()', true),
224
'ERROR [my-function()]: Something failed'
225
);
226
227
@include assert-equal(
228
error('Generic error', null, true),
229
'ERROR: Generic error'
230
);
231
}
232
```
233
234
### Testing Complex Error Scenarios
235
236
```scss
237
@use 'pkg:sass-true' as *;
238
239
@function validate-config($config) {
240
@if meta.type-of($config) != 'map' {
241
@return error(
242
'Configuration must be a map',
243
'validate-config()',
244
true
245
);
246
}
247
248
$required-keys: ('theme', 'breakpoints');
249
@each $key in $required-keys {
250
@if not map-has-key($config, $key) {
251
@return error(
252
'Missing required key: #{$key}',
253
'validate-config()',
254
true
255
);
256
}
257
}
258
259
@return $config;
260
}
261
262
@include test('Configuration validation') {
263
@include assert-equal(
264
validate-config('not-a-map'),
265
'ERROR [validate-config()]: Configuration must be a map'
266
);
267
268
@include assert-equal(
269
validate-config((theme: 'dark')),
270
'ERROR [validate-config()]: Missing required key: breakpoints'
271
);
272
273
@include assert-equal(
274
validate-config((theme: 'dark', breakpoints: (mobile: 768px))),
275
(theme: 'dark', breakpoints: (mobile: 768px))
276
);
277
}
278
```
279
280
### Error Handling in Mixins with Conditional Output
281
282
When using error handling in mixins, use conditional blocks to prevent generating invalid CSS:
283
284
```scss
285
@mixin width($length) {
286
@if (meta.type-of($length) != 'number') {
287
@include error('$length must be a number', 'width()', true);
288
} @else {
289
// Only generate CSS if no error
290
width: $length;
291
}
292
}
293
294
@include test('Conditional mixin output') {
295
@include assert('Should output error comment only') {
296
@include output {
297
@include width('invalid');
298
}
299
300
@include contains-string('ERROR [width()]');
301
// Should NOT contain 'width:' property
302
}
303
}
304
```
305
306
## Error State Testing Patterns
307
308
### Comprehensive Error Testing
309
310
```scss
311
@include describe('Error Handling') {
312
@include describe('Input Validation') {
313
@include it('handles null values') {
314
@include assert-equal(
315
my-function(null),
316
'ERROR [my-function()]: Input cannot be null'
317
);
318
}
319
320
@include it('handles wrong types') {
321
@include assert-equal(
322
my-function('string'),
323
'ERROR [my-function()]: Expected number, got string'
324
);
325
}
326
}
327
328
@include describe('Boundary Conditions') {
329
@include it('handles zero values') {
330
@include assert-equal(
331
divide-function(10, 0),
332
'ERROR [divide-function()]: Division by zero'
333
);
334
}
335
}
336
}
337
```
338
339
### Mixed Success and Error Testing
340
341
```scss
342
@include test('Function handles all cases correctly') {
343
// Test successful cases
344
@include assert-equal(safe-function(10), 20);
345
@include assert-equal(safe-function(0), 0);
346
347
// Test error cases
348
@include assert-equal(
349
safe-function(-1),
350
'ERROR [safe-function()]: Negative values not allowed'
351
);
352
353
@include assert-equal(
354
safe-function(null),
355
'ERROR [safe-function()]: Value required'
356
);
357
}
358
```