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    /// Unknown/unresearched Group Formations block type.
219    #[error("Unknown/unsupported Group Formations block type: {0}.")]
220    DecodingGroupFormationsUnknownBlockType(u32),
221
222    /// File is not CA_VP8 or IVF format.
223    #[error("This file is neither a CA_VP8 nor an IVF file.")]
224    DecodingCAVP8UnsupportedFormat,
225
226    /// CA_VP8 frame size invalid.
227    #[error("Incorrect/Unknown Frame size.")]
228    DecodingCAVP8IncorrectOrUnknownFrameSize,
229
230    // ESF Errors
231
232    /// ESF signature not supported.
233    #[error("Unsupported signature: {0:#X} {1:#X}.")]
234    DecodingESFUnsupportedSignature(u8, u8),
235
236    /// ESF data type not supported.
237    #[error("Unsupported data type: {0}.")]
238    DecodingESFUnsupportedDataType(u8),
239
240    /// ESF record name not in string table.
241    #[error("Record name not found: {0}.")]
242    DecodingESFRecordNameNotFound(u16),
243
244    /// ESF string not in string table.
245    #[error("String not found: {0}.")]
246    DecodingESFStringNotFound(u32),
247
248    /// ESF encoding signature not supported.
249    #[error("Unsupported signature: {0}.")]
250    EncodingESFUnsupportedSignature(String),
251
252    // Font File Errors
253
254    /// Font file signature not supported.
255    #[error("Unsupported signature: {0:#X?}.")]
256    DecodingFontUnsupportedSignature(Vec<u8>),
257
258    // FastBin Errors
259
260    /// FastBin signature not supported.
261    #[error("Unsupported signature: {0:#X?}.")]
262    DecodingFastBinUnsupportedSignature(Vec<u8>),
263
264    /// FastBin version not supported for decoding.
265    #[error("Unsupported version {1} for type {0}.")]
266    DecodingFastBinUnsupportedVersion(String, u16),
267
268    /// FastBin version not supported for encoding.
269    #[error("Unsupported version {1} for type {0}.")]
270    EncodingFastBinUnsupportedVersion(String, u16),
271
272    // RigidModel Errors
273
274    /// RigidModel signature not supported.
275    #[error("Unsupported signature: {0:#X?}.")]
276    DecodingRigidModelUnsupportedSignature(Vec<u8>),
277
278    /// RigidModel version not supported.
279    #[error("Unknown rigid model version: {0}")]
280    DecodingRigidModelUnsupportedVersion(u32),
281
282    /// RigidModel material type not supported.
283    #[error("Unsupported material type: {0}.")]
284    DecodingRigidModelUnsupportedMaterialType(u16),
285
286    /// RigidModel texture type unknown.
287    #[error("Unsupported texture type: {0}.")]
288    DecodingRigidModelUnknownTextureType(i32),
289
290    /// RigidModel vertex format unknown.
291    #[error("Unsupported vertex format: {0}.")]
292    DecodingRigidModelUnknownVertexFormat(u16),
293
294    /// RigidModel vertex format incompatible with material.
295    #[error("Unsupported vertex format {0} for material {1}.")]
296    DecodingRigidModelUnsupportedVertexFormatForMaterial(u16, u16),
297
298    /// Group Formations unknown enum value.
299    #[error("Unknown group formations {0} value: {1}.")]
300    DecodingGroupFormationsUnknownEnumValue(String, u32),
301
302    // Table Decoding Errors
303
304    /// Combined colour field decoding failed.
305    #[error("Error decoding combined colour.")]
306    DecodingTableCombinedColour,
307
308    // SoundBank Errors
309
310    /// SoundBank BKHD header section missing.
311    #[error("Header section not found. This shouldn't happen.")]
312    SoundBankBKHDNotFound,
313
314    /// SoundBank section type not supported.
315    #[error("Unsupported section {0} found in SoundBank.")]
316    SoundBankUnsupportedSectionFound(String),
317
318    /// SoundBank object version not supported.
319    #[error("Unsupported version {0} for object of type {1} found in SoundBank.")]
320    SoundBankUnsupportedVersionFound(u32, String),
321
322    /// SoundBank language ID not supported.
323    #[error("Unsupported language id {0} found in SoundBank.")]
324    SoundBankUnsupportedLanguageFound(u32),
325
326    /// SoundBank object type not supported.
327    #[error("Unsupported object type {0} found in SoundBank.")]
328    SoundBankUnsupportedObjectTypeFound(u8),
329
330    // Table Field Errors
331
332    /// Table field decoding failed.
333    #[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.")]
334    DecodingTableFieldError(u32, u32, String),
335
336    /// Table sequence field index out of bounds.
337    #[error("Error trying to get the data for a {3} on Row {0}, Cell {1}: invalid ending index {2}.")]
338    DecodingTableFieldSequenceIndexError(u32, u32, usize, String),
339
340    /// Table sequence field data invalid.
341    #[error("Error trying to get the data for a {3} on Row {0}, Cell {1}: {2}.")]
342    DecodingTableFieldSequenceDataError(u32, u32, String, String),
343
344    /// Table decoding incomplete with partial data.
345    #[error("Error trying to decode a table: {0}. The incomplete table is: {1:#?}.")]
346    DecodingTableIncomplete(String, Box<TableInMemory>),
347
348    // Extra Data Errors
349
350    /// Required extra decoding data missing.
351    #[error("Missing extra data required to decode the file. This means the programmer messed up the code while that tries to decode files.")]
352    DecodingMissingExtraData,
353
354    /// Extra data field missing or invalid.
355    #[error("Missing or invalid extra data provided: \"{0}\"")]
356    DecodingMissingExtraDataField(String),
357
358    /// File decoding not supported for selected game.
359    #[error("Decoding of this file is unsupported for game: \"{0}\"")]
360    DecodingUnsupportedGameSelected(String),
361
362    // Table Encoding Errors
363
364    /// Table row field count mismatch.
365    #[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. Rows must match Definition::fields_processed() (bitwise/enum/colour groups collapsed), not the raw Definition::fields() layout.")]
366    TableRowWrongFieldCount(usize, usize),
367
368    /// Table field type mismatch.
369    #[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}\".")]
370    EncodingTableWrongFieldType(String, String),
371
372    // Schema/Definition Errors
373
374    /// Table definition missing and file empty.
375    #[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.")]
376    DecodingDBNoDefinitionsFoundAndEmptyFile,
377
378    /// Table definition missing from schema.
379    #[error("There are no definitions for this specific version of the table in the Schema.")]
380    DecodingDBNoDefinitionsFound,
381
382    /// File not a valid DB table.
383    #[error("This is either not a DB Table, or it's a DB Table but it's corrupted.")]
384    DecodingDBNotADBTable,
385
386    /// File not a valid Loc table.
387    #[error("This is either not a Loc Table, or it's a Loc Table but it's corrupted.")]
388    DecodingLocNotALocTable,
389
390    /// File not a valid Matched Combat table.
391    #[error("This is either not a Matched Combat Table, or it's a Matched Combat Table but it's corrupted.")]
392    DecodingMatchedCombatNotAMatchedCombatTable,
393
394    /// File not a valid Unit Variant.
395    #[error("This is either not an Unit Variant, or it's an Unit Variant but it's corrupted.")]
396    DecodingUnitVariantNotAUnitVariant,
397
398    /// File size mismatch with expected size.
399    #[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.")]
400    DecodingMismatchSizeError(usize, usize),
401
402    // Version Errors
403
404    /// Portrait Settings version not supported.
405    #[error("This file's version ({0}) is not yet supported.")]
406    DecodingPortraitSettingUnsupportedVersion(usize),
407
408    /// Generic unsupported version error.
409    #[error("This file's version ({0}) is not yet supported.")]
410    DecodingUnsupportedVersion(usize),
411
412    /// Anim Fragment version not supported.
413    #[error("This file's version ({0}) is not yet supported.")]
414    DecodingAnimFragmentUnsupportedVersion(usize),
415
416    /// Matched Combat version not supported.
417    #[error("This file's version ({0}) is not yet supported.")]
418    DecodingMatchedCombatUnsupportedVersion(usize),
419
420    // File Type Errors
421
422    /// Decoded data type doesn't match expected file type.
423    #[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.")]
424    DecodedDataDoesNotMatchFileType(FileType, FileType),
425
426    /// SoundPacked decoding not supported for game.
427    #[error("Decoding of SoundPacked files is not supported for this game: {0}.")]
428    DecodingSoundPackedUnsupportedGame(String),
429
430    /// SoundPacked encoding not supported for game.
431    #[error("Encoding of SoundPacked files is not supported for this game: {0}.")]
432    EncodingSoundPackedUnsupportedGame(String),
433
434    /// Required extra encoding data missing.
435    #[error("Missing extra data required to encode the file. This means the programmer messed up the code while that tries to decode files.")]
436    EncodingMissingExtraData,
437
438    /// Invalid state participant value.
439    #[error("Invalid state participant value: {0}")]
440    InvalidStateParticipantValue(u32),
441
442    // Git Repository Errors
443
444    /// Git repository download or update failed.
445    #[error("There was an error while downloading/updating the following git repository: {0}.")]
446    GitErrorDownloadFromRepo(String),
447
448    /// No updates available for git repository.
449    #[error("No updates available for the following git repository: {0}.")]
450    GitErrorNoUpdatesAvailable(String),
451
452    // Lazy Loading Errors
453
454    /// File data changed on disk during lazy loading.
455    #[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.
456
457        Basically, this means your Pack got partially corrupted.
458
459        If you see this message in a program that's not RPFM,... ask its author what to do.
460
461        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.
462
463        That will create a Pack with only the files that were confirmed as non-corrupted, so at least you can recover their data.
464
465        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.
466
467        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.")]
468    FileSourceChanged(String),
469
470    // Size/Limit Errors
471
472    /// File too large for container.
473    #[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.")]
474    DataTooBigForContainer(String, u64, usize, String),
475
476    // File Operation Errors
477
478    /// File not found in pack.
479    #[error("The following file hasn't been found: {0}.")]
480    FileNotFound(String),
481
482    /// File not yet decoded.
483    #[error("The following file hasn't yet been decoded: {0}.")]
484    FileNotDecoded(String),
485
486    /// File not yet cached.
487    #[error("The following file hasn't yet been cached: {0}.")]
488    FileNotCached(String),
489
490    /// Reserved file operation blocked.
491    #[error("Operation not allowed: reserved file detected.")]
492    ReservedFiles,
493
494    /// Empty destination path.
495    #[error("Operation not allowed: destiny is blank for your file.")]
496    EmptyDestiny,
497
498    /// No packs provided to operation.
499    #[error("No Packs provided.")]
500    NoPacksProvided,
501
502    /// Live export has no files to export.
503    #[error("No files to export.")]
504    LiveExportNoFilesToExport,
505
506    // Build/Update Errors
507
508    /// Startpos build error.
509    #[error("{0}")]
510    BuildStartposError(String),
511
512    /// Animation IDs update error.
513    #[error("{0}")]
514    UpdateAnimIdsError(String),
515
516    // SQLite Errors
517
518    /// SQLite connection pool not initialized.
519    #[error("The SQLite connection pool hasn't been initialized yet.")]
520    MissingSQLitePool,
521
522    /// Path missing filename component.
523    #[error("The path {0} doesn't have an identifiable filename.")]
524    PathMissingFileName(String),
525
526    // Dependencies Cache Errors
527
528    /// Dependencies cache not generated or outdated.
529    #[error("The dependencies cache has not been generated or it's outdated and need regenerating.")]
530    DependenciesCacheNotGeneratedorOutOfDate,
531
532    /// File not found in dependencies cache.
533    #[error("The file with the path {0} hasn't been found in the dependencies cache.")]
534    DependenciesCacheFileNotFound(String),
535
536    // Definition Update Errors
537
538    /// Table already has latest definition.
539    #[error("This table already has the newer definition available.")]
540    NoDefinitionUpdateAvailable,
541
542    /// Table not found in game files for comparison.
543    #[error("This table cannot be found in the Game Files, so it cannot be automatically updated (yet).")]
544    NoTableInGameFilesToCompare,
545
546    // Assembly Kit Errors
547
548    /// Assembly Kit version not supported.
549    #[error("Operations over the Assembly Kit of version {0} are not currently supported.")]
550    AssemblyKitUnsupportedVersion(i16),
551
552    /// Assembly Kit folder not found or readable.
553    #[error("The Assembly Kit Folder could not be read. You may need to install the Assembly Kit.")]
554    AssemblyKitNotFound,
555
556    /// Table not found in Assembly Kit.
557    #[error("The table {0} was not found in the Assembly Kit.")]
558    AssemblyKitTableNotFound(String),
559
560    /// Assembly Kit table blacklisted.
561    #[error("One of the Assembly Kit Tables you tried to decode has been blacklisted due to issues.")]
562    AssemblyKitTableTableIgnored,
563
564    /// Localisable fields file not found.
565    #[error("The `Localisable Fields` file hasn't been found.")]
566    AssemblyKitLocalisableFieldsNotFound,
567
568    /// Relationships file not found.
569    #[error("The relationships file hasn't been found.")]
570    AssemblyKitExtraRelationshipsNotFound,
571
572    /// Raw table import missing definition.
573    #[error("The raw table you tried to import is missing a definition.")]
574    RawTableMissingDefinition,
575
576    // TSV Import Errors
577
578    /// TSV import row/field error.
579    #[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.")]
580    ImportTSVIncorrectRow(usize, usize),
581
582    /// TSV file incompatible or wrong type.
583    #[error("This TSV file either belongs to another table, to a localization File, it's broken or it's incompatible with RPFM.")]
584    ImportTSVWrongTypeTable,
585
586    /// TSV file has invalid version.
587    #[error("This TSV file has an invalid version value at line 1.")]
588    ImportTSVInvalidVersion,
589
590    /// TSV file missing or invalid path.
591    #[error("This TSV file has an invalid or missing file path value at line 1.")]
592    ImportTSVInvalidOrMissingPath,
593
594    /// TSV export requested for a file type that isn't DB or Loc.
595    #[error("TSV export is only supported for DB and Loc files.")]
596    ExportTSVUnsupportedFileType,
597
598    // File Merge Errors
599
600    /// Merge requires multiple files.
601    #[error("You need to pass more than one file to merge.")]
602    RFileMergeOnlyOneFileProvided,
603
604    /// Cannot merge files of different types.
605    #[error("Merging files of different types is not supported.")]
606    RFileMergeDifferentTypes,
607
608    /// Cannot merge tables with different names.
609    #[error("Merging tables with different table names is not supported.")]
610    RFileMergeTablesDifferentNames,
611
612    /// Table merge requires at least two tables.
613    #[error("Merging tables needs at least two tables.")]
614    RFileMergeTablesNotEnoughTablesProvided,
615
616    /// File type doesn't support merging.
617    #[error("Merging files of type {0} is not supported.")]
618    RFileMergeNotSupportedForType(String),
619
620    // Group Formation Errors
621
622    /// Group formation block type unknown.
623    #[error("Block Type {0} is not supported.")]
624    GroupFormationUnknownBlockType(u32),
625
626    // Patch Errors
627
628    /// Cannot patch empty pack.
629    #[error("This Pack is empty, so we can't patch it.")]
630    PatchSiegeAIEmptyPack,
631
632    /// No patchable files in pack.
633    #[error("There are not files in this Pack that could be patched/deleted.")]
634    PatchSiegeAINoPatchableFiles,
635
636    /// No schema provided when required.
637    #[error("No Schema provided.")]
638    SchemaNotProvided,
639
640    // IVF Errors
641
642    /// Invalid subtraction during IVF processing.
643    #[error("Invalid subtraction when processing an IVF file. This means the something went wrong when saving the IVF file.")]
644    IVFInvalidSubstraction,
645
646    // Steam Workshop Errors
647
648    /// Game doesn't support Steam Workshop.
649    #[error("The game {0} doesn't support the Steam Workshop.")]
650    GameDoesntSupportWorkshop(String),
651
652    /// SteamID not recognized as Total War game.
653    #[error("The SteamID {0} doesn't belong to any known Total War game.")]
654    SteamIDDoesntBelongToKnownGame(u64),
655
656    // Global Search/Replace Errors
657
658    /// Global replace requires same byte length without regex.
659    #[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.")]
660    GlobalSearchReplaceRequiresSameLengthAndNotRegex,
661
662    /// IO error with associated path.
663    #[error("Error in path: {1}. {0}")]
664    IOErrorPath(Box<Self>, PathBuf),
665
666    // Translation Errors
667
668    /// No translation found.
669    #[error("No translation could be found.")]
670    TranslatorCouldNotLoadTranslation,
671
672    // GameInfo Errors
673
674    /// GameInfo missing from pack-reading function.
675    #[error("GameInfo has not been provided to the pack-reading function when reading the pack.")]
676    GameInfoMissingFromDecodingFunction,
677
678    /// GameInfo missing from pack-saving function.
679    #[error("GameInfo has not been provided to the pack-saving function when saving the pack.")]
680    GameInfoMissingFromEncodingFunction,
681
682    // External Library Error Wrappers
683
684    /// Wrapper for [`std::io::Error`] errors.
685    #[error(transparent)]
686    IOError(#[from] std::io::Error),
687
688    /// Wrapper for [`git2::Error`] errors.
689    #[cfg(feature = "integration_git")]
690    #[error(transparent)]
691    GitError(#[from] git2::Error),
692
693    /// Wrapper for [`ron::Error`] errors.
694    #[error(transparent)]
695    RonError(#[from] ron::Error),
696
697    /// Wrapper for [`ron::error::SpannedError`] errors.
698    #[error(transparent)]
699    RonSpannedError(#[from] ron::error::SpannedError),
700
701    /// Wrapper for [`csv::Error`] errors.
702    #[error(transparent)]
703    CSVError(#[from] csv::Error),
704
705    /// Wrapper for [`serde_json::Error`] errors.
706    #[error(transparent)]
707    JsonError(#[from] serde_json::Error),
708
709    /// Wrapper for [`std::array::TryFromSliceError`] errors.
710    #[error(transparent)]
711    TryFromSliceError(#[from] std::array::TryFromSliceError),
712
713    /// Wrapper for [`std::time::SystemTimeError`] errors.
714    #[error(transparent)]
715    SystemTimeError(#[from] std::time::SystemTimeError),
716
717    /// Wrapper for [`std::path::StripPrefixError`] errors.
718    #[error(transparent)]
719    StripPrefixError(#[from] std::path::StripPrefixError),
720
721    /// Wrapper for [`r2d2::Error`] errors.
722    #[cfg(feature = "integration_sqlite")]
723    #[error(transparent)]
724    R2D2Error(#[from] r2d2::Error),
725
726    /// Wrapper for [`rusqlite::Error`] errors.
727    #[cfg(feature = "integration_sqlite")]
728    #[error(transparent)]
729    RusqliteError(#[from] rusqlite::Error),
730
731    /// Wrapper for [`toml::ser::Error`] errors.
732    #[error(transparent)]
733    TomlError(#[from] toml::ser::Error),
734
735    /// Wrapper for [`bitcode::Error`] errors.
736    #[cfg(feature = "support_error_bitcode")]
737    #[error(transparent)]
738    BitcodeError(#[from] bitcode::Error),
739
740    /// Wrapper for [`serde_xml_rs::Error`] errors.
741    #[cfg(feature = "integration_assembly_kit")]
742    #[error(transparent)]
743    XmlRsError(#[from] serde_xml_rs::Error),
744
745    /// Wrapper for [`log::SetLoggerError`] errors.
746    #[error(transparent)]
747    LogError(#[from] log::SetLoggerError),
748
749    /// Wrapper for [`lz4_flex::frame::Error`] errors.
750    #[error(transparent)]
751    Lz4Error(#[from] lz4_flex::frame::Error),
752
753    /// Wrapper for [`lzma_rs::error::Error`] errors.
754    #[error(transparent)]
755    LzmaError(#[from] lzma_rs::error::Error),
756
757    /// Wrapper for [`image::ImageError`] errors.
758    #[error(transparent)]
759    ImageError(#[from] image::ImageError),
760
761    /// Wrapper for [`dds::DecodingError`] errors.
762    #[error(transparent)]
763    DDSDecError(#[from] dds::DecodingError),
764
765    /// Wrapper for [`dds::EncodingError`] errors.
766    #[error(transparent)]
767    DDSEncError(#[from] dds::EncodingError),
768
769    /// DDS colour format not supported.
770    #[error("Unsupported colour format for DDS files.")]
771    DecodingDDSColourFormatUnsupported,
772}