0
# Exception Handling
1
2
This document covers Liquibase's comprehensive exception hierarchy and error management system for handling various failure scenarios.
3
4
## Imports
5
6
```java { .api }
7
// Base exceptions
8
import liquibase.exception.LiquibaseException;
9
10
// Database exceptions
11
import liquibase.exception.DatabaseException;
12
import liquibase.exception.DatabaseHistoryException;
13
import liquibase.exception.LockException;
14
15
// Validation exceptions
16
import liquibase.exception.ValidationFailedException;
17
import liquibase.exception.ValidationErrors;
18
import liquibase.exception.CommandValidationException;
19
20
// Parsing exceptions
21
import liquibase.exception.ChangeLogParseException;
22
import liquibase.exception.LiquibaseParseException;
23
import liquibase.exception.UnknownChangelogFormatException;
24
25
// Execution exceptions
26
import liquibase.exception.CommandExecutionException;
27
import liquibase.exception.MigrationFailedException;
28
import liquibase.exception.RollbackFailedException;
29
import liquibase.exception.RollbackImpossibleException;
30
31
// Precondition exceptions
32
import liquibase.exception.PreconditionFailedException;
33
import liquibase.exception.PreconditionErrorException;
34
35
// Setup and configuration exceptions
36
import liquibase.exception.SetupException;
37
import liquibase.exception.UnexpectedLiquibaseException;
38
```
39
40
## Base Exception Class
41
42
### LiquibaseException
43
44
The base exception class for all Liquibase-related errors.
45
46
```java { .api }
47
/**
48
* Base exception for all Liquibase errors
49
*/
50
public class LiquibaseException extends Exception {
51
52
/**
53
* Create exception with message
54
* @param message Error message
55
*/
56
public LiquibaseException(String message)
57
58
/**
59
* Create exception with message and cause
60
* @param message Error message
61
* @param cause Underlying cause
62
*/
63
public LiquibaseException(String message, Throwable cause)
64
65
/**
66
* Create exception with cause only
67
* @param cause Underlying cause
68
*/
69
public LiquibaseException(Throwable cause)
70
}
71
```
72
73
## Database Exceptions
74
75
### DatabaseException
76
77
General database-related errors including connection and SQL execution problems.
78
79
```java { .api }
80
/**
81
* Exception for database-related errors
82
*/
83
public class DatabaseException extends LiquibaseException {
84
85
/**
86
* Create database exception with message
87
* @param message Error message describing database issue
88
*/
89
public DatabaseException(String message)
90
91
/**
92
* Create database exception with message and cause
93
* @param message Error message
94
* @param cause Underlying database exception (often SQLException)
95
*/
96
public DatabaseException(String message, Throwable cause)
97
}
98
```
99
100
### DatabaseHistoryException
101
102
Errors related to Liquibase's database history tracking tables.
103
104
```java { .api }
105
/**
106
* Exception for database history table errors
107
*/
108
public class DatabaseHistoryException extends DatabaseException {
109
110
/**
111
* Create history exception with message
112
* @param message Error message related to history tracking
113
*/
114
public DatabaseHistoryException(String message)
115
116
/**
117
* Create history exception with message and cause
118
* @param message Error message
119
* @param cause Underlying cause
120
*/
121
public DatabaseHistoryException(String message, Throwable cause)
122
}
123
```
124
125
### LockException
126
127
Errors related to database locking mechanisms for preventing concurrent migrations.
128
129
```java { .api }
130
/**
131
* Exception for database locking errors
132
*/
133
public class LockException extends LiquibaseException {
134
135
/**
136
* Create lock exception with message
137
* @param message Error message related to database locking
138
*/
139
public LockException(String message)
140
141
/**
142
* Create lock exception with message and cause
143
* @param message Error message
144
* @param cause Underlying cause
145
*/
146
public LockException(String message, Throwable cause)
147
}
148
```
149
150
## Validation Exceptions
151
152
### ValidationFailedException
153
154
Thrown when changelog or changeset validation fails.
155
156
```java { .api }
157
/**
158
* Exception for validation failures
159
*/
160
public class ValidationFailedException extends LiquibaseException {
161
162
/**
163
* Create validation exception with message
164
* @param message Validation failure description
165
*/
166
public ValidationFailedException(String message)
167
168
/**
169
* Create validation exception with validation errors
170
* @param validationErrors Collection of validation errors
171
*/
172
public ValidationFailedException(ValidationErrors validationErrors)
173
174
/**
175
* Get validation errors if available
176
* @return ValidationErrors object, or null
177
*/
178
public ValidationErrors getValidationErrors()
179
}
180
```
181
182
### ValidationErrors
183
184
Container for multiple validation error messages.
185
186
```java { .api }
187
/**
188
* Collection of validation errors
189
*/
190
public class ValidationErrors {
191
192
/**
193
* Check if any errors exist
194
* @return true if validation errors were found
195
*/
196
public boolean hasErrors()
197
198
/**
199
* Get list of error messages
200
* @return List of validation error messages
201
*/
202
public List<String> getErrorMessages()
203
204
/**
205
* Add validation error message
206
* @param message Error message to add
207
*/
208
public void addError(String message)
209
210
/**
211
* Get count of validation errors
212
* @return Number of validation errors
213
*/
214
public int getErrorCount()
215
}
216
```
217
218
### CommandValidationException
219
220
Validation errors specific to command execution and arguments.
221
222
```java { .api }
223
/**
224
* Exception for command validation errors
225
*/
226
public class CommandValidationException extends ValidationFailedException {
227
228
/**
229
* Create command validation exception
230
* @param message Command validation error message
231
*/
232
public CommandValidationException(String message)
233
234
/**
235
* Create command validation exception with cause
236
* @param message Error message
237
* @param cause Underlying cause
238
*/
239
public CommandValidationException(String message, Throwable cause)
240
}
241
```
242
243
## Parsing Exceptions
244
245
### ChangeLogParseException
246
247
Errors encountered while parsing changelog files.
248
249
```java { .api }
250
/**
251
* Exception for changelog parsing errors
252
*/
253
public class ChangeLogParseException extends LiquibaseParseException {
254
255
/**
256
* Create parse exception with message
257
* @param message Parsing error description
258
*/
259
public ChangeLogParseException(String message)
260
261
/**
262
* Create parse exception with message and cause
263
* @param message Error message
264
* @param cause Underlying parsing exception
265
*/
266
public ChangeLogParseException(String message, Throwable cause)
267
}
268
```
269
270
### LiquibaseParseException
271
272
General parsing errors for various Liquibase file formats.
273
274
```java { .api }
275
/**
276
* Exception for general parsing errors
277
*/
278
public class LiquibaseParseException extends LiquibaseException {
279
280
/**
281
* Create parse exception with message
282
* @param message Parsing error message
283
*/
284
public LiquibaseParseException(String message)
285
286
/**
287
* Create parse exception with message and cause
288
* @param message Error message
289
* @param cause Underlying cause
290
*/
291
public LiquibaseParseException(String message, Throwable cause)
292
}
293
```
294
295
### UnknownChangelogFormatException
296
297
Thrown when Liquibase encounters an unsupported changelog file format.
298
299
```java { .api }
300
/**
301
* Exception for unknown changelog format
302
*/
303
public class UnknownChangelogFormatException extends ChangeLogParseException {
304
305
/**
306
* Create unknown format exception
307
* @param message Description of unknown format
308
*/
309
public UnknownChangelogFormatException(String message)
310
}
311
```
312
313
## Execution Exceptions
314
315
### CommandExecutionException
316
317
Errors during command execution in the modern command framework.
318
319
```java { .api }
320
/**
321
* Exception for command execution failures
322
*/
323
public class CommandExecutionException extends LiquibaseException {
324
325
/**
326
* Create command execution exception
327
* @param message Command execution error message
328
*/
329
public CommandExecutionException(String message)
330
331
/**
332
* Create command execution exception with cause
333
* @param message Error message
334
* @param cause Underlying cause of execution failure
335
*/
336
public CommandExecutionException(String message, Throwable cause)
337
}
338
```
339
340
### MigrationFailedException
341
342
Errors during database migration execution.
343
344
```java { .api }
345
/**
346
* Exception for migration execution failures
347
*/
348
public class MigrationFailedException extends LiquibaseException {
349
350
/**
351
* Create migration exception with message
352
* @param message Migration failure description
353
*/
354
public MigrationFailedException(String message)
355
356
/**
357
* Create migration exception with message and cause
358
* @param message Error message
359
* @param cause Underlying cause of migration failure
360
*/
361
public MigrationFailedException(String message, Throwable cause)
362
}
363
```
364
365
### RollbackFailedException
366
367
Errors during rollback operations.
368
369
```java { .api }
370
/**
371
* Exception for rollback execution failures
372
*/
373
public class RollbackFailedException extends LiquibaseException {
374
375
/**
376
* Create rollback exception with message
377
* @param message Rollback failure description
378
*/
379
public RollbackFailedException(String message)
380
381
/**
382
* Create rollback exception with message and cause
383
* @param message Error message
384
* @param cause Underlying cause of rollback failure
385
*/
386
public RollbackFailedException(String message, Throwable cause)
387
}
388
```
389
390
### RollbackImpossibleException
391
392
Thrown when a rollback operation cannot be performed due to irreversible changes.
393
394
```java { .api }
395
/**
396
* Exception when rollback is not possible
397
*/
398
public class RollbackImpossibleException extends RollbackFailedException {
399
400
/**
401
* Create rollback impossible exception
402
* @param message Explanation of why rollback is impossible
403
*/
404
public RollbackImpossibleException(String message)
405
406
/**
407
* Create rollback impossible exception with cause
408
* @param message Error message
409
* @param cause Underlying cause
410
*/
411
public RollbackImpossibleException(String message, Throwable cause)
412
}
413
```
414
415
## Precondition Exceptions
416
417
### PreconditionFailedException
418
419
Thrown when preconditions defined in changesets fail.
420
421
```java { .api }
422
/**
423
* Exception for precondition check failures
424
*/
425
public class PreconditionFailedException extends LiquibaseException {
426
427
/**
428
* Create precondition exception with message
429
* @param message Precondition failure description
430
*/
431
public PreconditionFailedException(String message)
432
433
/**
434
* Create precondition exception with message and cause
435
* @param message Error message
436
* @param cause Underlying cause
437
*/
438
public PreconditionFailedException(String message, Throwable cause)
439
}
440
```
441
442
### PreconditionErrorException
443
444
Errors encountered while evaluating preconditions (different from precondition failures).
445
446
```java { .api }
447
/**
448
* Exception for precondition evaluation errors
449
*/
450
public class PreconditionErrorException extends LiquibaseException {
451
452
/**
453
* Create precondition error exception
454
* @param message Precondition evaluation error message
455
*/
456
public PreconditionErrorException(String message)
457
458
/**
459
* Create precondition error exception with cause
460
* @param message Error message
461
* @param cause Underlying cause
462
*/
463
public PreconditionErrorException(String message, Throwable cause)
464
}
465
```
466
467
## Setup and Configuration Exceptions
468
469
### SetupException
470
471
Errors during Liquibase initialization and setup.
472
473
```java { .api }
474
/**
475
* Exception for setup and initialization errors
476
*/
477
public class SetupException extends LiquibaseException {
478
479
/**
480
* Create setup exception with message
481
* @param message Setup error description
482
*/
483
public SetupException(String message)
484
485
/**
486
* Create setup exception with message and cause
487
* @param message Error message
488
* @param cause Underlying cause
489
*/
490
public SetupException(String message, Throwable cause)
491
}
492
```
493
494
### UnexpectedLiquibaseException
495
496
Runtime errors that are unexpected and typically indicate bugs.
497
498
```java { .api }
499
/**
500
* Exception for unexpected runtime errors
501
*/
502
public class UnexpectedLiquibaseException extends RuntimeException {
503
504
/**
505
* Create unexpected exception with message
506
* @param message Unexpected error description
507
*/
508
public UnexpectedLiquibaseException(String message)
509
510
/**
511
* Create unexpected exception with message and cause
512
* @param message Error message
513
* @param cause Underlying cause
514
*/
515
public UnexpectedLiquibaseException(String message, Throwable cause)
516
517
/**
518
* Create unexpected exception with cause only
519
* @param cause Underlying cause
520
*/
521
public UnexpectedLiquibaseException(Throwable cause)
522
}
523
```
524
525
## Error Handling Examples
526
527
### Basic Exception Handling
528
529
```java { .api }
530
import liquibase.Liquibase;
531
import liquibase.exception.*;
532
533
try {
534
// Execute Liquibase operation
535
Liquibase liquibase = new Liquibase("changelog.xml", resourceAccessor, database);
536
liquibase.update((String) null);
537
538
} catch (DatabaseException e) {
539
System.err.println("Database error: " + e.getMessage());
540
// Handle database connectivity or SQL issues
541
542
} catch (ValidationFailedException e) {
543
System.err.println("Validation failed: " + e.getMessage());
544
545
// Check for detailed validation errors
546
ValidationErrors errors = e.getValidationErrors();
547
if (errors != null && errors.hasErrors()) {
548
for (String error : errors.getErrorMessages()) {
549
System.err.println(" - " + error);
550
}
551
}
552
553
} catch (ChangeLogParseException e) {
554
System.err.println("Changelog parsing error: " + e.getMessage());
555
// Handle XML/YAML/JSON parsing issues
556
557
} catch (MigrationFailedException e) {
558
System.err.println("Migration failed: " + e.getMessage());
559
// Handle changeset execution failures
560
561
} catch (LiquibaseException e) {
562
System.err.println("General Liquibase error: " + e.getMessage());
563
// Handle any other Liquibase-specific errors
564
}
565
```
566
567
### Command Framework Exception Handling
568
569
```java { .api }
570
import liquibase.command.CommandScope;
571
import liquibase.command.CommandResults;
572
import liquibase.exception.CommandExecutionException;
573
import liquibase.exception.CommandValidationException;
574
575
try {
576
CommandScope updateCommand = new CommandScope("update")
577
.addArgumentValue("changelogFile", "db/changelog/db.changelog-master.xml")
578
.addArgumentValue("url", "jdbc:h2:mem:test")
579
.addArgumentValue("username", "sa")
580
.addArgumentValue("password", "");
581
582
CommandResults results = updateCommand.execute();
583
584
} catch (CommandValidationException e) {
585
System.err.println("Command validation error: " + e.getMessage());
586
// Handle invalid command arguments
587
588
} catch (CommandExecutionException e) {
589
System.err.println("Command execution failed: " + e.getMessage());
590
591
// Check for nested exceptions
592
Throwable cause = e.getCause();
593
if (cause instanceof DatabaseException) {
594
System.err.println("Underlying database error: " + cause.getMessage());
595
} else if (cause instanceof ValidationFailedException) {
596
System.err.println("Underlying validation error: " + cause.getMessage());
597
}
598
}
599
```
600
601
### Rollback Exception Handling
602
603
```java { .api }
604
try {
605
liquibase.rollback("version-1.0", "production");
606
607
} catch (RollbackImpossibleException e) {
608
System.err.println("Rollback impossible: " + e.getMessage());
609
// Handle cases where rollback cannot be performed
610
// May need manual intervention or different approach
611
612
} catch (RollbackFailedException e) {
613
System.err.println("Rollback failed: " + e.getMessage());
614
// Handle rollback execution failures
615
// Database may be in inconsistent state
616
617
} catch (DatabaseException e) {
618
System.err.println("Database error during rollback: " + e.getMessage());
619
// Handle database connectivity issues during rollback
620
}
621
```
622
623
### Lock Exception Handling
624
625
```java { .api }
626
try {
627
liquibase.update((String) null);
628
629
} catch (LockException e) {
630
System.err.println("Database lock error: " + e.getMessage());
631
632
// Check if another process is running
633
try {
634
DatabaseChangeLogLock[] locks = liquibase.listLocks();
635
if (locks.length > 0) {
636
System.err.println("Found " + locks.length + " active locks:");
637
for (DatabaseChangeLogLock lock : locks) {
638
System.err.println(" Lock ID: " + lock.getId());
639
System.err.println(" Locked by: " + lock.getLockedBy());
640
System.err.println(" Lock time: " + lock.getLockGranted());
641
}
642
}
643
644
// Optionally force release locks (use with caution)
645
// liquibase.forceReleaseLocks();
646
647
} catch (LiquibaseException lockCheckException) {
648
System.err.println("Could not check locks: " + lockCheckException.getMessage());
649
}
650
}
651
```
652
653
### Comprehensive Error Handling
654
655
```java { .api }
656
public class LiquibaseErrorHandler {
657
658
public void handleLiquibaseOperation(Runnable operation) {
659
try {
660
operation.run();
661
662
} catch (ValidationFailedException e) {
663
handleValidationError(e);
664
665
} catch (ChangeLogParseException e) {
666
handleParsingError(e);
667
668
} catch (DatabaseException e) {
669
handleDatabaseError(e);
670
671
} catch (MigrationFailedException e) {
672
handleMigrationError(e);
673
674
} catch (RollbackFailedException e) {
675
handleRollbackError(e);
676
677
} catch (LockException e) {
678
handleLockError(e);
679
680
} catch (CommandExecutionException e) {
681
handleCommandError(e);
682
683
} catch (LiquibaseException e) {
684
handleGeneralError(e);
685
686
} catch (UnexpectedLiquibaseException e) {
687
handleUnexpectedError(e);
688
}
689
}
690
691
private void handleValidationError(ValidationFailedException e) {
692
System.err.println("=== Validation Error ===");
693
System.err.println("Message: " + e.getMessage());
694
695
ValidationErrors errors = e.getValidationErrors();
696
if (errors != null && errors.hasErrors()) {
697
System.err.println("Validation errors (" + errors.getErrorCount() + "):");
698
for (String error : errors.getErrorMessages()) {
699
System.err.println(" - " + error);
700
}
701
}
702
}
703
704
private void handleParsingError(ChangeLogParseException e) {
705
System.err.println("=== Parsing Error ===");
706
System.err.println("Message: " + e.getMessage());
707
708
if (e instanceof UnknownChangelogFormatException) {
709
System.err.println("Unknown changelog format detected.");
710
System.err.println("Ensure changelog file has correct extension (.xml, .yaml, .json, .sql)");
711
}
712
713
Throwable cause = e.getCause();
714
if (cause != null) {
715
System.err.println("Underlying cause: " + cause.getMessage());
716
}
717
}
718
719
private void handleDatabaseError(DatabaseException e) {
720
System.err.println("=== Database Error ===");
721
System.err.println("Message: " + e.getMessage());
722
723
if (e instanceof DatabaseHistoryException) {
724
System.err.println("Issue with Liquibase tracking tables.");
725
System.err.println("Check DATABASECHANGELOG and DATABASECHANGELOGLOCK tables.");
726
}
727
728
Throwable cause = e.getCause();
729
if (cause instanceof SQLException) {
730
SQLException sqlEx = (SQLException) cause;
731
System.err.println("SQL Error Code: " + sqlEx.getErrorCode());
732
System.err.println("SQL State: " + sqlEx.getSQLState());
733
}
734
}
735
736
private void handleMigrationError(MigrationFailedException e) {
737
System.err.println("=== Migration Error ===");
738
System.err.println("Message: " + e.getMessage());
739
System.err.println("Migration failed during execution.");
740
System.err.println("Database may be in partially updated state.");
741
System.err.println("Review failed changeset and fix before retrying.");
742
}
743
744
private void handleRollbackError(RollbackFailedException e) {
745
System.err.println("=== Rollback Error ===");
746
System.err.println("Message: " + e.getMessage());
747
748
if (e instanceof RollbackImpossibleException) {
749
System.err.println("Rollback impossible - changes may be irreversible.");
750
System.err.println("Manual intervention may be required.");
751
} else {
752
System.err.println("Rollback execution failed.");
753
System.err.println("Database may be in inconsistent state.");
754
}
755
}
756
757
private void handleLockError(LockException e) {
758
System.err.println("=== Lock Error ===");
759
System.err.println("Message: " + e.getMessage());
760
System.err.println("Another Liquibase process may be running.");
761
System.err.println("Wait for other process to complete or force release locks.");
762
}
763
764
private void handleCommandError(CommandExecutionException e) {
765
System.err.println("=== Command Error ===");
766
System.err.println("Message: " + e.getMessage());
767
768
Throwable cause = e.getCause();
769
if (cause != null) {
770
System.err.println("Caused by: " + cause.getClass().getSimpleName() +
771
": " + cause.getMessage());
772
}
773
}
774
775
private void handleGeneralError(LiquibaseException e) {
776
System.err.println("=== General Liquibase Error ===");
777
System.err.println("Message: " + e.getMessage());
778
System.err.println("Type: " + e.getClass().getSimpleName());
779
}
780
781
private void handleUnexpectedError(UnexpectedLiquibaseException e) {
782
System.err.println("=== Unexpected Error (Possible Bug) ===");
783
System.err.println("Message: " + e.getMessage());
784
System.err.println("This may indicate a bug in Liquibase.");
785
System.err.println("Consider reporting this error with full stack trace.");
786
e.printStackTrace();
787
}
788
}
789
```
790
791
### Recovery Strategies
792
793
```java { .api }
794
public class LiquibaseRecovery {
795
796
public void attemptRecovery(Liquibase liquibase) {
797
try {
798
// First try to release any stale locks
799
liquibase.forceReleaseLocks();
800
801
// Validate changelog
802
liquibase.validate();
803
804
// Attempt operation again
805
liquibase.update((String) null);
806
807
} catch (LockException e) {
808
System.err.println("Could not release locks: " + e.getMessage());
809
810
} catch (ValidationFailedException e) {
811
System.err.println("Changelog validation still failing after lock release");
812
// Manual intervention required
813
814
} catch (DatabaseException e) {
815
System.err.println("Database connectivity issues persist");
816
// Check database connection and credentials
817
818
} catch (LiquibaseException e) {
819
System.err.println("Recovery failed: " + e.getMessage());
820
// Manual investigation required
821
}
822
}
823
}
824
```