Skip to main content

rpfm_lib/error/
mod.rs

1//---------------------------------------------------------------------------//
2// Copyright (c) 2017-2026 Ismael Gutiérrez González. All rights reserved.
3//
4// This file is part of the Rusted PackFile Manager (RPFM) project,
5// which can be found here: https://github.com/Frodo45127/rpfm.
6//
7// This file is licensed under the MIT license, which can be found here:
8// https://github.com/Frodo45127/rpfm/blob/master/LICENSE.
9//---------------------------------------------------------------------------//
10
11//! Error types and result handling for the RPFM library.
12//!
13//! This module defines [`RLibError`], a comprehensive error type that covers all possible
14//! error conditions that can occur when working with Total War PackFiles and related files.
15//!
16//! # Error Categories
17//!
18//! The errors are organized into several categories:
19//! - **Compression/Decompression**: Errors related to file compression operations
20//! - **Encoding/Decoding**: Errors when reading or writing various file formats
21//! - **File I/O**: General file reading and writing errors
22//! - **Schema/Definition**: Errors related to missing or invalid schemas and definitions
23//! - **Game-Specific**: Errors specific to certain Total War games or features
24//! - **External Libraries**: Wrapped errors from third-party dependencies
25//!
26//! # Usage
27//!
28//! This module provides a custom [`Result`] type alias that uses [`RLibError`] as the default error type:
29//!
30//! ```ignore
31//! use rpfm_lib::error::Result;
32//!
33//! fn do_something() -> Result<String> {
34//!     // Returns Result<String, RLibError>
35//!     Ok("success".to_string())
36//! }
37//! ```
38
39use std::path::PathBuf;
40
41use thiserror::Error;
42
43use crate::files::{FileType, table::local::TableInMemory};
44
45/// Custom [`Result`] type alias that uses [`RLibError`] as the default error type.
46///
47/// This is a convenience type alias that allows functions to return `Result<T>` instead
48/// of `Result<T, RLibError>`, making function signatures cleaner throughout the codebase.
49///
50/// [`Result`]: std::result::Result
51pub type Result<T, E = RLibError> = core::result::Result<T, E>;
52
53/// Comprehensive error type for all RPFM library operations.
54///
55/// This enum covers all possible error conditions that can occur when working with
56/// Total War PackFiles and related file formats. Each variant includes descriptive
57/// error messages via the `#[error]` attribute from the `thiserror` crate.
58///
59/// # Error Display
60///
61/// All errors implement [`std::fmt::Display`] and provide user-friendly error messages.
62/// The error messages are automatically generated from the `#[error(...)]` attributes.
63#[derive(Error, Debug)]
64pub enum RLibError {
65    // Compression/Decompression Errors
66    
67    /// Error when data compression fails.
68    #[error("This file's compression failed for some reason. This means this File cannot be compressed RPFM.")]
69    DataCannotBeCompressed,
70
71    /// Error when data decompression fails.
72    #[error("This is a compressed file and the decompression failed for some reason. This means this File cannot be opened in RPFM.")]
73    DataCannotBeDecompressed,
74
75    // Manifest Errors
76
77    /// Manifest file for selected game not found.
78    #[error("The manifest for the Game Selected hasn't been found.")]
79    ManifestFileNotFound,
80
81    /// Error parsing game's manifest.txt file.
82    #[error("Error while parsing the manifest.txt file of the game selected: {0}.")]
83    ManifestFileParseError(String),
84
85    // Binary Decoding Errors
86
87    /// No more bytes available for decoding.
88    #[error("There are no more bytes to decode in the data you provided.")]
89    DecodingNotMoreBytesToDecode,
90
91    /// Invalid byte value for boolean decoding.
92    #[error("Error trying to decode \"{0}\" as boolean: invalid value.")]
93    DecodingBoolError(u8),
94
95    /// No bytes remaining for number decoding.
96    #[error("Error trying to decode a byte as a number: No bytes left to decode.")]
97    DecodingNoBytesLeftError,
98
99    /// Insufficient bytes for type decoding.
100    #[error("Error trying to decode an {0} value: Required bytes: {1}. Provided bytes: {2:?}.")]
101    DecodingNotEnoughBytesToDecodeForType(String, usize, Option<usize>),
102
103    /// Wrapper for integer parsing errors.
104    #[error(transparent)]
105    DecodeIntError(#[from] std::num::ParseIntError),
106
107    /// Wrapper for float parsing errors.
108    #[error(transparent)]
109    DecodeFloatError(#[from] std::num::ParseFloatError),
110
111    /// Wrapper for UTF-8 string conversion errors.
112    #[error(transparent)]
113    DecodeUTF8Error(#[from] std::string::FromUtf8Error),
114
115    /// Wrapper for UTF-8 string slice validation errors.
116    #[error(transparent)]
117    DecodeUTF8StrError(#[from] std::str::Utf8Error),
118
119    /// Wrapper for UTF-16 string conversion errors.
120    #[error(transparent)]
121    DecodeUTF16Error(#[from] std::string::FromUtf16Error),
122
123    /// UTF-16 string has odd byte count.
124    #[error("Error trying to decode an UTF-16 String. We expected an even amount of bytes, but instead we have {0} bytes.")]
125    DecodeUTF16UnevenInputError(usize),
126
127    /// ISO-8859-1 to UTF-8 conversion failed.
128    #[error("Error trying to convert an ISO8859-1 String to an UTF-8 String: {0}.")]
129    DecodeUTF8FromISO8859Error(String),
130
131    /// String size cannot be determined.
132    #[error("Error trying to decode an {0}: Not enough bytes to get his size.")]
133    DecodingStringSizeError(String),
134
135    /// Optional string missing boolean prefix.
136    #[error("Error trying to decode an {0}: The first byte is not a boolean.")]
137    DecodingOptionalStringBoolError(String),
138
139    /// Null-terminated string missing terminator.
140    #[error("Error trying to read an 00-Terminated String: No byte 00 found.")]
141    DecodingString0TeminatedNo0Error,
142
143    /// Padded string exceeds maximum length.
144    #[error("Error trying to encode an {0}: \"{1}\" has a length of {2} chars, but his length should be less or equal than {3}.")]
145    EncodingPaddedStringError(String, String, usize, usize),
146
147    // Game Installation Errors
148
149    /// Game install type not supported.
150    #[error("The game with the key \"{0}\" is not supported for the install type \"{1}\".")]
151    GameInstallTypeNotSupported(String, String),
152
153    /// Launch command not supported for game install type.
154    #[error("Launch commands for game \"{0}\", install type \"{1}\" are not currently supported.")]
155    GameInstallLaunchNotSupported(String, String),
156
157    /// Invalid boolean value string.
158    #[error("Error trying to convert the following value to a bool: {0}.")]
159    ParseBoolError(String),
160
161    /// File or folder cannot be read.
162    #[error("Error while trying to read the following file/folder: {0}. \
163        This means that path may not be readable (permissions? other programs locking access to it?) or may not exists at all.")]
164    ReadFileFolderError(String),
165
166    // PackFile Structure Errors
167
168    /// PackFile header corrupted or unsupported.
169    #[error("The header of the Pack is incomplete, unsupported or damaged.")]
170    PackHeaderNotComplete,
171
172    /// PackFile subheader missing or corrupted.
173    #[error("The subheader of the Pack is incomplete, unsupported or damaged.")]
174    PackSubHeaderMissing,
175
176    /// PackFile indexes corrupted or incomplete.
177    #[error("The indexes of the Pack are incomplete, unsupported or damaged")]
178    PackIndexesNotComplete,
179
180    /// Unknown PFH file type.
181    #[error("Unknown PFH File Type: {0}")]
182    UnknownPFHFileType(String),
183
184    /// Unknown PFH version.
185    #[error("Unknown PFH Version: {0}")]
186    UnknownPFHVersion(String),
187
188    // File Format Errors
189
190    /// Unknown ESF signature string.
191    #[error("Unknown ESF Signature: {0}")]
192    UnknownESFSignature(String),
193
194    /// Unknown ESF signature bytes.
195    #[error("Unknown ESF Signature: {0:#X} {1:#X}")]
196    UnknownESFSignatureBytes(u8, u8),
197
198    /// Unknown Empire File line type.
199    #[error("Unknown EF Line Type: {0}")]
200    UnknownEFLineType(String),
201
202    /// Unknown pipe type.
203    #[error("Unknown Pipe Type: {0}")]
204    UnknownPipeType(String),
205
206    /// CS2 migration not supported for this game.
207    #[error("Migration to this game is not yet supported for cs2.parsed files.")]
208    GameDoesntSupportCs2Migration,
209
210    /// Text file encoding unsupported or not a text file.
211    #[error("This is either not a Text File, or a Text File using an unsupported encoding")]
212    DecodingTextUnsupportedEncodingOrNotATextFile,
213
214    /// Unknown anim table version.
215    #[error("This file has an unknown/unsupported version: {0}.")]
216    DecodingAnimsTableUnknownVersion(i32),
217
218    /// File is not CA_VP8 or IVF format.
219    #[error("This file is neither a CA_VP8 nor an IVF file.")]
220    DecodingCAVP8UnsupportedFormat,
221
222    /// CA_VP8 frame size invalid.
223    #[error("Incorrect/Unknown Frame size.")]
224    DecodingCAVP8IncorrectOrUnknownFrameSize,
225
226    // ESF Errors
227
228    /// ESF signature not supported.
229    #[error("Unsupported signature: {0:#X} {1:#X}.")]
230    DecodingESFUnsupportedSignature(u8, u8),
231
232    /// ESF data type not supported.
233    #[error("Unsupported data type: {0}.")]
234    DecodingESFUnsupportedDataType(u8),
235
236    /// ESF record name not in string table.
237    #[error("Record name not found: {0}.")]
238    DecodingESFRecordNameNotFound(u16),
239
240    /// ESF string not in string table.
241    #[error("String not found: {0}.")]
242    DecodingESFStringNotFound(u32),
243
244    /// ESF encoding signature not supported.
245    #[error("Unsupported signature: {0}.")]
246    EncodingESFUnsupportedSignature(String),
247
248    // Font File Errors
249
250    /// Font file signature not supported.
251    #[error("Unsupported signature: {0:#X?}.")]
252    DecodingFontUnsupportedSignature(Vec<u8>),
253
254    // FastBin Errors
255
256    /// FastBin signature not supported.
257    #[error("Unsupported signature: {0:#X?}.")]
258    DecodingFastBinUnsupportedSignature(Vec<u8>),
259
260    /// FastBin version not supported for decoding.
261    #[error("Unsupported version {1} for type {0}.")]
262    DecodingFastBinUnsupportedVersion(String, u16),
263
264    /// FastBin version not supported for encoding.
265    #[error("Unsupported version {1} for type {0}.")]
266    EncodingFastBinUnsupportedVersion(String, u16),
267
268    // RigidModel Errors
269
270    /// RigidModel signature not supported.
271    #[error("Unsupported signature: {0:#X?}.")]
272    DecodingRigidModelUnsupportedSignature(Vec<u8>),
273
274    /// RigidModel version not supported.
275    #[error("Unknown rigid model version: {0}")]
276    DecodingRigidModelUnsupportedVersion(u32),
277
278    /// RigidModel material type not supported.
279    #[error("Unsupported material type: {0}.")]
280    DecodingRigidModelUnsupportedMaterialType(u16),
281
282    /// RigidModel texture type unknown.
283    #[error("Unsupported texture type: {0}.")]
284    DecodingRigidModelUnknownTextureType(i32),
285
286    /// RigidModel vertex format unknown.
287    #[error("Unsupported vertex format: {0}.")]
288    DecodingRigidModelUnknownVertexFormat(u16),
289
290    /// RigidModel vertex format incompatible with material.
291    #[error("Unsupported vertex format {0} for material {1}.")]
292    DecodingRigidModelUnsupportedVertexFormatForMaterial(u16, u16),
293
294    /// Group Formations unknown enum value.
295    #[error("Unknown group formations {0} value: {1}.")]
296    DecodingGroupFormationsUnknownEnumValue(String, u32),
297
298    // Table Decoding Errors
299
300    /// Combined colour field decoding failed.
301    #[error("Error decoding combined colour.")]
302    DecodingTableCombinedColour,
303
304    // SoundBank Errors
305
306    /// SoundBank BKHD header section missing.
307    #[error("Header section not found. This shouldn't happen.")]
308    SoundBankBKHDNotFound,
309
310    /// SoundBank section type not supported.
311    #[error("Unsupported section {0} found in SoundBank.")]
312    SoundBankUnsupportedSectionFound(String),
313
314    /// SoundBank object version not supported.
315    #[error("Unsupported version {0} for object of type {1} found in SoundBank.")]
316    SoundBankUnsupportedVersionFound(u32, String),
317
318    /// SoundBank language ID not supported.
319    #[error("Unsupported language id {0} found in SoundBank.")]
320    SoundBankUnsupportedLanguageFound(u32),
321
322    /// SoundBank object type not supported.
323    #[error("Unsupported object type {0} found in SoundBank.")]
324    SoundBankUnsupportedObjectTypeFound(u8),
325
326    // Table Field Errors
327
328    /// Table field decoding failed.
329    #[error("Error trying to decode the Row {0}, Cell {1} as a {2} value: either the value is not a {2}, or there are insufficient bytes left to decode it as a {2} value.")]
330    DecodingTableFieldError(u32, u32, String),
331
332    /// Table sequence field index out of bounds.
333    #[error("Error trying to get the data for a {3} on Row {0}, Cell {1}: invalid ending index {2}.")]
334    DecodingTableFieldSequenceIndexError(u32, u32, usize, String),
335
336    /// Table sequence field data invalid.
337    #[error("Error trying to get the data for a {3} on Row {0}, Cell {1}: {2}.")]
338    DecodingTableFieldSequenceDataError(u32, u32, String, String),
339
340    /// Table decoding incomplete with partial data.
341    #[error("Error trying to decode a table: {0}. The incomplete table is: {1:#?}.")]
342    DecodingTableIncomplete(String, Box<TableInMemory>),
343
344    // Extra Data Errors
345
346    /// Required extra decoding data missing.
347    #[error("Missing extra data required to decode the file. This means the programmer messed up the code while that tries to decode files.")]
348    DecodingMissingExtraData,
349
350    /// Extra data field missing or invalid.
351    #[error("Missing or invalid extra data provided: \"{0}\"")]
352    DecodingMissingExtraDataField(String),
353
354    /// File decoding not supported for selected game.
355    #[error("Decoding of this file is unsupported for game: \"{0}\"")]
356    DecodingUnsupportedGameSelected(String),
357
358    // Table Encoding Errors
359
360    /// Table row field count mismatch.
361    #[error("Error while trying to save a row from a table: We expected a row with \"{0}\" fields, but we got a row with \"{1}\" fields instead.")]
362    TableRowWrongFieldCount(usize, usize),
363
364    /// Table field type mismatch.
365    #[error("Error while trying to save a row from a table: We expected a field of type \"{0}\", but we got a field of type \"{1}\".")]
366    EncodingTableWrongFieldType(String, String),
367
368    // Schema/Definition Errors
369
370    /// Table definition missing and file empty.
371    #[error("There are no definitions for this specific version of the table in the Schema and the table is empty. This means this table cannot be open nor decoded.")]
372    DecodingDBNoDefinitionsFoundAndEmptyFile,
373
374    /// Table definition missing from schema.
375    #[error("There are no definitions for this specific version of the table in the Schema.")]
376    DecodingDBNoDefinitionsFound,
377
378    /// File not a valid DB table.
379    #[error("This is either not a DB Table, or it's a DB Table but it's corrupted.")]
380    DecodingDBNotADBTable,
381
382    /// File not a valid Loc table.
383    #[error("This is either not a Loc Table, or it's a Loc Table but it's corrupted.")]
384    DecodingLocNotALocTable,
385
386    /// File not a valid Matched Combat table.
387    #[error("This is either not a Matched Combat Table, or it's a Matched Combat Table but it's corrupted.")]
388    DecodingMatchedCombatNotAMatchedCombatTable,
389
390    /// File not a valid Unit Variant.
391    #[error("This is either not an Unit Variant, or it's an Unit Variant but it's corrupted.")]
392    DecodingUnitVariantNotAUnitVariant,
393
394    /// File size mismatch with expected size.
395    #[error("This file's reported size is '{0}' bytes, but we expected it to be '{1}' bytes. This means that the definition of the table is incorrect (only on tables, it's usually this), the decoding logic in RPFM is broken for this file, or this file is corrupted.")]
396    DecodingMismatchSizeError(usize, usize),
397
398    // Version Errors
399
400    /// Portrait Settings version not supported.
401    #[error("This file's version ({0}) is not yet supported.")]
402    DecodingPortraitSettingUnsupportedVersion(usize),
403
404    /// Generic unsupported version error.
405    #[error("This file's version ({0}) is not yet supported.")]
406    DecodingUnsupportedVersion(usize),
407
408    /// Anim Fragment version not supported.
409    #[error("This file's version ({0}) is not yet supported.")]
410    DecodingAnimFragmentUnsupportedVersion(usize),
411
412    /// Matched Combat version not supported.
413    #[error("This file's version ({0}) is not yet supported.")]
414    DecodingMatchedCombatUnsupportedVersion(usize),
415
416    // File Type Errors
417
418    /// Decoded data type doesn't match expected file type.
419    #[error("This file is expected to be of {0} type, but the data provided is of {1} type. If you see this, 99% sure it is a bug.")]
420    DecodedDataDoesNotMatchFileType(FileType, FileType),
421
422    /// SoundPacked decoding not supported for game.
423    #[error("Decoding of SoundPacked files is not supported for this game: {0}.")]
424    DecodingSoundPackedUnsupportedGame(String),
425
426    /// SoundPacked encoding not supported for game.
427    #[error("Encoding of SoundPacked files is not supported for this game: {0}.")]
428    EncodingSoundPackedUnsupportedGame(String),
429
430    /// Required extra encoding data missing.
431    #[error("Missing extra data required to encode the file. This means the programmer messed up the code while that tries to decode files.")]
432    EncodingMissingExtraData,
433
434    /// Invalid state participant value.
435    #[error("Invalid state participant value: {0}")]
436    InvalidStateParticipantValue(u32),
437
438    // Git Repository Errors
439
440    /// Git repository download or update failed.
441    #[error("There was an error while downloading/updating the following git repository: {0}.")]
442    GitErrorDownloadFromRepo(String),
443
444    /// No updates available for git repository.
445    #[error("No updates available for the following git repository: {0}.")]
446    GitErrorNoUpdatesAvailable(String),
447
448    // Lazy Loading Errors
449
450    /// File data changed on disk during lazy loading.
451    #[error("The file's data for file ({0}) has been altered on disk by another program since the last time it was accessed by us. If you see this, it means you're using lazy-loading and another program has altered the data on disk before this program loaded it to memory.
452
453        Basically, this means your Pack got partially corrupted.
454
455        If you see this message in a program that's not RPFM,... ask its author what to do.
456
457        If you see this message in RPFM, your original Pack on disk should still be safe, and RPFM can recover part of the files inside the open PackFile: DB tables, Locs and any PackedFile open before this message appeared. To do that, go to 'Special Stuff' and hit 'Rescue PackFile', then choose a folder to save the clean Pack.
458
459        That will create a Pack with only the files that were confirmed as non-corrupted, so at least you can recover their data.
460
461        And some final words: if you intentionally opened the same Pack in two instances of RPFM and tried to save on both, that was the cause of this. No, it's not a bug in RPFM. No, I can't magically fix it. It's how lazy-loading data from disk works. If you don't like it, you can disable lazy-loading in the settings. You'll be resistant to Pack corruption, but RPFM will use a ton more RAM. So... choose your poison.
462
463        Note: if this message appeared while adding files from a Pack, you're save. Just close the 'Add From PackFile' tab and open it again.")]
464    FileSourceChanged(String),
465
466    // Size/Limit Errors
467
468    /// File too large for container.
469    #[error("At least one of the files (`{3}`) on this {0} is too big for it. The maximum supported size for files is {1}, but your file has {2} bytes.")]
470    DataTooBigForContainer(String, u64, usize, String),
471
472    // File Operation Errors
473
474    /// File not found in pack.
475    #[error("The following file hasn't been found: {0}.")]
476    FileNotFound(String),
477
478    /// File not yet decoded.
479    #[error("The following file hasn't yet been decoded: {0}.")]
480    FileNotDecoded(String),
481
482    /// File not yet cached.
483    #[error("The following file hasn't yet been cached: {0}.")]
484    FileNotCached(String),
485
486    /// Reserved file operation blocked.
487    #[error("Operation not allowed: reserved file detected.")]
488    ReservedFiles,
489
490    /// Empty destination path.
491    #[error("Operation not allowed: destiny is blank for your file.")]
492    EmptyDestiny,
493
494    /// No packs provided to operation.
495    #[error("No Packs provided.")]
496    NoPacksProvided,
497
498    /// Live export has no files to export.
499    #[error("No files to export.")]
500    LiveExportNoFilesToExport,
501
502    // Build/Update Errors
503
504    /// Startpos build error.
505    #[error("{0}")]
506    BuildStartposError(String),
507
508    /// Animation IDs update error.
509    #[error("{0}")]
510    UpdateAnimIdsError(String),
511
512    // SQLite Errors
513
514    /// SQLite connection pool not initialized.
515    #[error("The SQLite connection pool hasn't been initialized yet.")]
516    MissingSQLitePool,
517
518    /// Path missing filename component.
519    #[error("The path {0} doesn't have an identifiable filename.")]
520    PathMissingFileName(String),
521
522    // Dependencies Cache Errors
523
524    /// Dependencies cache not generated or outdated.
525    #[error("The dependencies cache has not been generated or it's outdated and need regenerating.")]
526    DependenciesCacheNotGeneratedorOutOfDate,
527
528    /// File not found in dependencies cache.
529    #[error("The file with the path {0} hasn't been found in the dependencies cache.")]
530    DependenciesCacheFileNotFound(String),
531
532    // Definition Update Errors
533
534    /// Table already has latest definition.
535    #[error("This table already has the newer definition available.")]
536    NoDefinitionUpdateAvailable,
537
538    /// Table not found in game files for comparison.
539    #[error("This table cannot be found in the Game Files, so it cannot be automatically updated (yet).")]
540    NoTableInGameFilesToCompare,
541
542    // Assembly Kit Errors
543
544    /// Assembly Kit version not supported.
545    #[error("Operations over the Assembly Kit of version {0} are not currently supported.")]
546    AssemblyKitUnsupportedVersion(i16),
547
548    /// Assembly Kit folder not found or readable.
549    #[error("The Assembly Kit Folder could not be read. You may need to install the Assembly Kit.")]
550    AssemblyKitNotFound,
551
552    /// Table not found in Assembly Kit.
553    #[error("The table {0} was not found in the Assembly Kit.")]
554    AssemblyKitTableNotFound(String),
555
556    /// Assembly Kit table blacklisted.
557    #[error("One of the Assembly Kit Tables you tried to decode has been blacklisted due to issues.")]
558    AssemblyKitTableTableIgnored,
559
560    /// Localisable fields file not found.
561    #[error("The `Localisable Fields` file hasn't been found.")]
562    AssemblyKitLocalisableFieldsNotFound,
563
564    /// Relationships file not found.
565    #[error("The relationships file hasn't been found.")]
566    AssemblyKitExtraRelationshipsNotFound,
567
568    /// Raw table import missing definition.
569    #[error("The raw table you tried to import is missing a definition.")]
570    RawTableMissingDefinition,
571
572    // TSV Import Errors
573
574    /// TSV import row/field error.
575    #[error("This TSV file has an error in the row {0}, field {1} (both starting at 0). Please, check it and make sure the value in that field is a valid value for that column.")]
576    ImportTSVIncorrectRow(usize, usize),
577
578    /// TSV file incompatible or wrong type.
579    #[error("This TSV file either belongs to another table, to a localization File, it's broken or it's incompatible with RPFM.")]
580    ImportTSVWrongTypeTable,
581
582    /// TSV file has invalid version.
583    #[error("This TSV file has an invalid version value at line 1.")]
584    ImportTSVInvalidVersion,
585
586    /// TSV file missing or invalid path.
587    #[error("This TSV file has an invalid or missing file path value at line 1.")]
588    ImportTSVInvalidOrMissingPath,
589
590    // File Merge Errors
591
592    /// Merge requires multiple files.
593    #[error("You need to pass more than one file to merge.")]
594    RFileMergeOnlyOneFileProvided,
595
596    /// Cannot merge files of different types.
597    #[error("Merging files of different types is not supported.")]
598    RFileMergeDifferentTypes,
599
600    /// Cannot merge tables with different names.
601    #[error("Merging tables with different table names is not supported.")]
602    RFileMergeTablesDifferentNames,
603
604    /// Table merge requires at least two tables.
605    #[error("Merging tables needs at least two tables.")]
606    RFileMergeTablesNotEnoughTablesProvided,
607
608    /// File type doesn't support merging.
609    #[error("Merging files of type {0} is not supported.")]
610    RFileMergeNotSupportedForType(String),
611
612    // Group Formation Errors
613
614    /// Group formation block type unknown.
615    #[error("Block Type {0} is not supported.")]
616    GroupFormationUnknownBlockType(u32),
617
618    // Patch Errors
619
620    /// Cannot patch empty pack.
621    #[error("This Pack is empty, so we can't patch it.")]
622    PatchSiegeAIEmptyPack,
623
624    /// No patchable files in pack.
625    #[error("There are not files in this Pack that could be patched/deleted.")]
626    PatchSiegeAINoPatchableFiles,
627
628    /// No schema provided when required.
629    #[error("No Schema provided.")]
630    SchemaNotProvided,
631
632    // IVF Errors
633
634    /// Invalid subtraction during IVF processing.
635    #[error("Invalid subtraction when processing an IVF file. This means the something went wrong when saving the IVF file.")]
636    IVFInvalidSubstraction,
637
638    // Steam Workshop Errors
639
640    /// Game doesn't support Steam Workshop.
641    #[error("The game {0} doesn't support the Steam Workshop.")]
642    GameDoesntSupportWorkshop(String),
643
644    /// SteamID not recognized as Total War game.
645    #[error("The SteamID {0} doesn't belong to any known Total War game.")]
646    SteamIDDoesntBelongToKnownGame(u64),
647
648    // Global Search/Replace Errors
649
650    /// Global replace requires same byte length without regex.
651    #[error("You're trying to perform a Global Replace on a type that doesn't support Regex replacement and requires that both, pattern and replacement have the exact same byte length. To avoid breaking files this program doesn't allow you to do that. Either make sure both strings have the exact same byte length, don't use regex, or use a hexadecimal editor.")]
652    GlobalSearchReplaceRequiresSameLengthAndNotRegex,
653
654    /// IO error with associated path.
655    #[error("Error in path: {1}. {0}")]
656    IOErrorPath(Box<Self>, PathBuf),
657
658    // Translation Errors
659
660    /// No translation found.
661    #[error("No translation could be found.")]
662    TranslatorCouldNotLoadTranslation,
663
664    // GameInfo Errors
665
666    /// GameInfo missing from pack-reading function.
667    #[error("GameInfo has not been provided to the pack-reading function when reading the pack.")]
668    GameInfoMissingFromDecodingFunction,
669
670    /// GameInfo missing from pack-saving function.
671    #[error("GameInfo has not been provided to the pack-saving function when saving the pack.")]
672    GameInfoMissingFromEncodingFunction,
673
674    // External Library Error Wrappers
675
676    /// Wrapper for [`std::io::Error`] errors.
677    #[error(transparent)]
678    IOError(#[from] std::io::Error),
679
680    /// Wrapper for [`git2::Error`] errors.
681    #[cfg(feature = "integration_git")]
682    #[error(transparent)]
683    GitError(#[from] git2::Error),
684
685    /// Wrapper for [`ron::Error`] errors.
686    #[error(transparent)]
687    RonError(#[from] ron::Error),
688
689    /// Wrapper for [`ron::error::SpannedError`] errors.
690    #[error(transparent)]
691    RonSpannedError(#[from] ron::error::SpannedError),
692
693    /// Wrapper for [`csv::Error`] errors.
694    #[error(transparent)]
695    CSVError(#[from] csv::Error),
696
697    /// Wrapper for [`serde_json::Error`] errors.
698    #[error(transparent)]
699    JsonError(#[from] serde_json::Error),
700
701    /// Wrapper for [`std::array::TryFromSliceError`] errors.
702    #[error(transparent)]
703    TryFromSliceError(#[from] std::array::TryFromSliceError),
704
705    /// Wrapper for [`std::time::SystemTimeError`] errors.
706    #[error(transparent)]
707    SystemTimeError(#[from] std::time::SystemTimeError),
708
709    /// Wrapper for [`std::path::StripPrefixError`] errors.
710    #[error(transparent)]
711    StripPrefixError(#[from] std::path::StripPrefixError),
712
713    /// Wrapper for [`r2d2::Error`] errors.
714    #[cfg(feature = "integration_sqlite")]
715    #[error(transparent)]
716    R2D2Error(#[from] r2d2::Error),
717
718    /// Wrapper for [`rusqlite::Error`] errors.
719    #[cfg(feature = "integration_sqlite")]
720    #[error(transparent)]
721    RusqliteError(#[from] rusqlite::Error),
722
723    /// Wrapper for [`toml::ser::Error`] errors.
724    #[error(transparent)]
725    TomlError(#[from] toml::ser::Error),
726
727    /// Wrapper for [`bitcode::Error`] errors.
728    #[cfg(feature = "support_error_bitcode")]
729    #[error(transparent)]
730    BitcodeError(#[from] bitcode::Error),
731
732    /// Wrapper for [`serde_xml_rs::Error`] errors.
733    #[cfg(feature = "integration_assembly_kit")]
734    #[error(transparent)]
735    XmlRsError(#[from] serde_xml_rs::Error),
736
737    /// Wrapper for [`log::SetLoggerError`] errors.
738    #[error(transparent)]
739    LogError(#[from] log::SetLoggerError),
740
741    /// Wrapper for [`lz4_flex::frame::Error`] errors.
742    #[error(transparent)]
743    Lz4Error(#[from] lz4_flex::frame::Error),
744
745    /// Wrapper for [`lzma_rs::error::Error`] errors.
746    #[error(transparent)]
747    LzmaError(#[from] lzma_rs::error::Error),
748
749    /// Wrapper for [`image::ImageError`] errors.
750    #[error(transparent)]
751    ImageError(#[from] image::ImageError),
752
753    /// Wrapper for [`dds::DecodingError`] errors.
754    #[error(transparent)]
755    DDSDecError(#[from] dds::DecodingError),
756
757    /// Wrapper for [`dds::EncodingError`] errors.
758    #[error(transparent)]
759    DDSEncError(#[from] dds::EncodingError),
760
761    /// DDS colour format not supported.
762    #[error("Unsupported colour format for DDS files.")]
763    DecodingDDSColourFormatUnsupported,
764}