use std::path::PathBuf;
use thiserror::Error;
use crate::conversion::ConversionReport;
use crate::validation::ValidationReport;
#[derive(Debug, Error)]
pub enum PanlabelError {
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Failed to parse IR JSON from {path}: {source}")]
IrJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write IR JSON to {path}: {source}")]
IrJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to parse COCO JSON from {path}: {source}")]
CocoJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write COCO JSON to {path}: {source}")]
CocoJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to parse Label Studio JSON from {path}: {source}")]
LabelStudioJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write Label Studio JSON to {path}: {source}")]
LabelStudioJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Invalid Label Studio JSON: {path}: {message}")]
LabelStudioJsonInvalid { path: PathBuf, message: String },
#[error("Failed to parse Labelbox JSON from {path}: {source}")]
LabelboxJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to parse Labelbox JSONL at {path}, line {line}: {message}")]
LabelboxJsonlParse {
path: PathBuf,
line: usize,
message: String,
},
#[error("Failed to write Labelbox JSON to {path}: {source}")]
LabelboxJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Invalid Labelbox JSON at {path}: {message}")]
LabelboxJsonInvalid { path: PathBuf, message: String },
#[error("Failed to parse Scale AI JSON from {path}: {source}")]
ScaleAiJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write Scale AI JSON to {path}: {source}")]
ScaleAiJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Invalid Scale AI JSON at {path}: {message}")]
ScaleAiJsonInvalid { path: PathBuf, message: String },
#[error("Failed to parse Unity Perception JSON from {path}: {source}")]
UnityPerceptionJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write Unity Perception JSON to {path}: {source}")]
UnityPerceptionJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Invalid Unity Perception JSON at {path}: {message}")]
UnityPerceptionJsonInvalid { path: PathBuf, message: String },
#[error("Failed to write Unity Perception dataset at {path}: {message}")]
UnityPerceptionWriteError { path: PathBuf, message: String },
#[error("Failed to parse SuperAnnotate JSON from {path}: {source}")]
SuperAnnotateJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write SuperAnnotate JSON to {path}: {source}")]
SuperAnnotateJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Invalid SuperAnnotate dataset layout at {path}: {message}")]
SuperAnnotateLayoutInvalid { path: PathBuf, message: String },
#[error("Failed to parse Supervisely JSON from {path}: {source}")]
SuperviselyJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write Supervisely JSON to {path}: {source}")]
SuperviselyJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Invalid Supervisely dataset layout at {path}: {message}")]
SuperviselyLayoutInvalid { path: PathBuf, message: String },
#[error("Failed to parse Cityscapes JSON from {path}: {source}")]
CityscapesJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write Cityscapes JSON to {path}: {source}")]
CityscapesJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Invalid Cityscapes dataset layout at {path}: {message}")]
CityscapesLayoutInvalid { path: PathBuf, message: String },
#[error("Invalid Marmot XML dataset layout at {path}: {message}")]
MarmotLayoutInvalid { path: PathBuf, message: String },
#[error("Failed to parse Marmot XML from {path}: {message}")]
MarmotXmlParse { path: PathBuf, message: String },
#[error("Marmot XML companion image not found for {path} (tried: {searched})")]
MarmotImageNotFound { path: PathBuf, searched: String },
#[error("Failed to read Marmot XML companion image dimensions from {path}: {source}")]
MarmotImageDimensionRead {
path: PathBuf,
#[source]
source: imagesize::ImageError,
},
#[error("Failed to write Marmot XML at {path}: {message}")]
MarmotWriteError { path: PathBuf, message: String },
#[error("Failed to parse TFOD CSV from {path}: {source}")]
TfodCsvParse {
path: PathBuf,
#[source]
source: csv::Error,
},
#[error("Failed to write TFOD CSV to {path}: {source}")]
TfodCsvWrite {
path: PathBuf,
#[source]
source: csv::Error,
},
#[error("Invalid TFOD CSV: {path}: {message}")]
TfodCsvInvalid { path: PathBuf, message: String },
#[error("Failed to read TFRecord from {path}: {message}")]
TfrecordRead { path: PathBuf, message: String },
#[error("Failed to write TFRecord to {path}: {message}")]
TfrecordWrite { path: PathBuf, message: String },
#[error("Invalid TFRecord at {path}: {message}")]
TfrecordInvalid { path: PathBuf, message: String },
#[error(
"Failed to decode TFRecord tf.train.Example at {path}, record {record_index}: {source}"
)]
TfrecordProtobufDecode {
path: PathBuf,
record_index: usize,
#[source]
source: prost::DecodeError,
},
#[error("Invalid YOLO dataset layout at {path}: {message}")]
YoloLayoutInvalid { path: PathBuf, message: String },
#[error("Failed to parse YOLO data.yaml at {path}: {source}")]
YoloDataYamlParse {
path: PathBuf,
#[source]
source: serde_yaml::Error,
},
#[error("Invalid YOLO classes.txt at {path}: {message}")]
YoloClassesTxtInvalid { path: PathBuf, message: String },
#[error("Failed to parse YOLO label row in {path}:{line}: {message}")]
YoloLabelParse {
path: PathBuf,
line: usize,
message: String,
},
#[error(
"No matching image found for label file {label_path} (expected stem: {expected_stem})"
)]
YoloImageNotFound {
label_path: PathBuf,
expected_stem: String,
},
#[error("Failed to read YOLO image dimensions from {path}: {source}")]
YoloImageDimensionRead {
path: PathBuf,
#[source]
source: imagesize::ImageError,
},
#[error("Failed to write YOLO dataset at {path}: {message}")]
YoloWriteError { path: PathBuf, message: String },
#[error("Invalid YOLO Keras-style TXT dataset at {path}: {message}")]
YoloKerasTxtInvalid { path: PathBuf, message: String },
#[error("Failed to parse YOLO Keras-style TXT row in {path}:{line}: {message}")]
YoloKerasTxtParse {
path: PathBuf,
line: usize,
message: String,
},
#[error("YOLO Keras-style TXT image not found: {image_ref} (searched from {path}; tried: {searched})")]
YoloKerasTxtImageNotFound {
path: PathBuf,
image_ref: String,
searched: String,
},
#[error("Failed to read YOLO Keras-style TXT image dimensions from {path}: {source}")]
YoloKerasTxtImageDimensionRead {
path: PathBuf,
#[source]
source: imagesize::ImageError,
},
#[error("Failed to write YOLO Keras-style TXT dataset at {path}: {message}")]
YoloKerasTxtWriteError { path: PathBuf, message: String },
#[error("Invalid VOC dataset layout at {path}: {message}")]
VocLayoutInvalid { path: PathBuf, message: String },
#[error("Failed to parse VOC XML from {path}: {message}")]
VocXmlParse { path: PathBuf, message: String },
#[error("Failed to write VOC dataset at {path}: {message}")]
VocWriteError { path: PathBuf, message: String },
#[error("Invalid KITTI dataset layout at {path}: {message}")]
KittiLayoutInvalid { path: PathBuf, message: String },
#[error("Failed to parse KITTI label in {path}:{line}: {message}")]
KittiLabelParse {
path: PathBuf,
line: usize,
message: String,
},
#[error("Failed to read KITTI image dimensions from {path}: {source}")]
KittiImageDimensionRead {
path: PathBuf,
#[source]
source: imagesize::ImageError,
},
#[error("Failed to write KITTI dataset at {path}: {message}")]
KittiWriteError { path: PathBuf, message: String },
#[error("Failed to parse VIA JSON from {path}: {source}")]
ViaJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write VIA JSON to {path}: {source}")]
ViaJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Invalid VIA JSON at {path}: {message}")]
ViaJsonInvalid { path: PathBuf, message: String },
#[error("VIA image not found: {image_ref} (searched from {path})")]
ViaImageNotFound { path: PathBuf, image_ref: String },
#[error("Failed to parse RetinaNet CSV from {path}: {source}")]
RetinanetCsvParse {
path: PathBuf,
#[source]
source: csv::Error,
},
#[error("Failed to write RetinaNet CSV to {path}: {source}")]
RetinanetCsvWrite {
path: PathBuf,
#[source]
source: csv::Error,
},
#[error("Invalid RetinaNet CSV: {path}: {message}")]
RetinanetCsvInvalid { path: PathBuf, message: String },
#[error("RetinaNet image not found: {image_ref} (searched from {path})")]
RetinanetImageNotFound { path: PathBuf, image_ref: String },
#[error("Failed to read RetinaNet image dimensions from {path}: {source}")]
RetinanetImageDimensionRead {
path: PathBuf,
#[source]
source: imagesize::ImageError,
},
#[error("Failed to parse Datumaro JSON from {path}: {source}")]
DatumaroJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write Datumaro JSON to {path}: {source}")]
DatumaroJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Invalid Datumaro JSON at {path}: {message}")]
DatumaroJsonInvalid { path: PathBuf, message: String },
#[error("Failed to parse WIDER Face TXT row in {path}:{line}: {message}")]
WiderFaceTxtParse {
path: PathBuf,
line: usize,
message: String,
},
#[error("Invalid WIDER Face TXT at {path}: {message}")]
WiderFaceTxtInvalid { path: PathBuf, message: String },
#[error("WIDER Face image not found: {image_ref} (searched from {path})")]
WiderFaceImageNotFound { path: PathBuf, image_ref: String },
#[error("Failed to read WIDER Face image dimensions from {path}: {source}")]
WiderFaceImageDimensionRead {
path: PathBuf,
#[source]
source: imagesize::ImageError,
},
#[error("Failed to parse OIDv4 TXT row in {path}:{line}: {message}")]
Oidv4TxtParse {
path: PathBuf,
line: usize,
message: String,
},
#[error("Invalid OIDv4 TXT at {path}: {message}")]
Oidv4TxtInvalid { path: PathBuf, message: String },
#[error("OIDv4 image not found: {image_ref} (searched from {path})")]
Oidv4ImageNotFound { path: PathBuf, image_ref: String },
#[error("Failed to read OIDv4 image dimensions from {path}: {source}")]
Oidv4ImageDimensionRead {
path: PathBuf,
#[source]
source: imagesize::ImageError,
},
#[error("Failed to parse BDD100K JSON from {path}: {source}")]
Bdd100kJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write BDD100K JSON to {path}: {source}")]
Bdd100kJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Invalid BDD100K JSON at {path}: {message}")]
Bdd100kJsonInvalid { path: PathBuf, message: String },
#[error("Failed to parse V7 Darwin JSON from {path}: {source}")]
V7DarwinJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write V7 Darwin JSON to {path}: {source}")]
V7DarwinJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Invalid V7 Darwin JSON at {path}: {message}")]
V7DarwinJsonInvalid { path: PathBuf, message: String },
#[error("Failed to parse Edge Impulse labels JSON from {path}: {source}")]
EdgeImpulseJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write Edge Impulse labels JSON to {path}: {source}")]
EdgeImpulseJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Invalid Edge Impulse labels JSON at {path}: {message}")]
EdgeImpulseJsonInvalid { path: PathBuf, message: String },
#[error("Failed to parse OpenLABEL JSON from {path}: {source}")]
OpenLabelJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write OpenLABEL JSON to {path}: {source}")]
OpenLabelJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Invalid OpenLABEL JSON at {path}: {message}")]
OpenLabelJsonInvalid { path: PathBuf, message: String },
#[error("Failed to parse VIA CSV from {path}: {source}")]
ViaCsvParse {
path: PathBuf,
#[source]
source: csv::Error,
},
#[error("Failed to write VIA CSV to {path}: {source}")]
ViaCsvWrite {
path: PathBuf,
#[source]
source: csv::Error,
},
#[error("Invalid VIA CSV at {path}: {message}")]
ViaCsvInvalid { path: PathBuf, message: String },
#[error("Failed to parse OpenImages CSV from {path}: {source}")]
OpenImagesCsvParse {
path: PathBuf,
#[source]
source: csv::Error,
},
#[error("Failed to write OpenImages CSV to {path}: {source}")]
OpenImagesCsvWrite {
path: PathBuf,
#[source]
source: csv::Error,
},
#[error("Invalid OpenImages CSV: {path}: {message}")]
OpenImagesCsvInvalid { path: PathBuf, message: String },
#[error("OpenImages image not found: {image_ref} (searched from {path})")]
OpenImagesImageNotFound { path: PathBuf, image_ref: String },
#[error("Failed to read OpenImages image dimensions from {path}: {source}")]
OpenImagesImageDimensionRead {
path: PathBuf,
#[source]
source: imagesize::ImageError,
},
#[error("Failed to parse Kaggle Wheat CSV from {path}: {source}")]
KaggleWheatCsvParse {
path: PathBuf,
#[source]
source: csv::Error,
},
#[error("Failed to write Kaggle Wheat CSV to {path}: {source}")]
KaggleWheatCsvWrite {
path: PathBuf,
#[source]
source: csv::Error,
},
#[error("Invalid Kaggle Wheat CSV: {path}: {message}")]
KaggleWheatCsvInvalid { path: PathBuf, message: String },
#[error("Failed to parse Google Cloud AutoML Vision CSV from {path}: {source}")]
AutoMlVisionCsvParse {
path: PathBuf,
#[source]
source: csv::Error,
},
#[error("Failed to write Google Cloud AutoML Vision CSV to {path}: {source}")]
AutoMlVisionCsvWrite {
path: PathBuf,
#[source]
source: csv::Error,
},
#[error("Invalid Google Cloud AutoML Vision CSV: {path}: {message}")]
AutoMlVisionCsvInvalid { path: PathBuf, message: String },
#[error("AutoML Vision image not found: {image_ref} (searched from {path})")]
AutoMlVisionImageNotFound { path: PathBuf, image_ref: String },
#[error("Failed to read AutoML Vision image dimensions from {path}: {source}")]
AutoMlVisionImageDimensionRead {
path: PathBuf,
#[source]
source: imagesize::ImageError,
},
#[error("Failed to parse Udacity CSV from {path}: {source}")]
UdacityCsvParse {
path: PathBuf,
#[source]
source: csv::Error,
},
#[error("Failed to write Udacity CSV to {path}: {source}")]
UdacityCsvWrite {
path: PathBuf,
#[source]
source: csv::Error,
},
#[error("Invalid Udacity CSV: {path}: {message}")]
UdacityCsvInvalid { path: PathBuf, message: String },
#[error("Failed to parse VoTT CSV from {path}: {source}")]
VottCsvParse {
path: PathBuf,
#[source]
source: csv::Error,
},
#[error("Failed to write VoTT CSV to {path}: {source}")]
VottCsvWrite {
path: PathBuf,
#[source]
source: csv::Error,
},
#[error("Invalid VoTT CSV: {path}: {message}")]
VottCsvInvalid { path: PathBuf, message: String },
#[error("VoTT CSV image not found: {image_ref} (searched from {path})")]
VottCsvImageNotFound { path: PathBuf, image_ref: String },
#[error("Failed to parse VoTT JSON from {path}: {source}")]
VottJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write VoTT JSON to {path}: {source}")]
VottJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Invalid VoTT JSON at {path}: {message}")]
VottJsonInvalid { path: PathBuf, message: String },
#[error("VoTT JSON image not found: {image_ref} (searched from {path})")]
VottJsonImageNotFound { path: PathBuf, image_ref: String },
#[error("Failed to parse IBM Cloud Annotations JSON from {path}: {source}")]
CloudAnnotationsJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write IBM Cloud Annotations JSON to {path}: {source}")]
CloudAnnotationsJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Invalid IBM Cloud Annotations JSON at {path}: {message}")]
CloudAnnotationsJsonInvalid { path: PathBuf, message: String },
#[error("IBM Cloud Annotations image not found: {image_ref} (searched from {path})")]
CloudAnnotationsImageNotFound { path: PathBuf, image_ref: String },
#[error("Invalid CVAT XML layout at {path}: {message}")]
CvatLayoutInvalid { path: PathBuf, message: String },
#[error("Failed to parse CVAT XML from {path}: {message}")]
CvatXmlParse { path: PathBuf, message: String },
#[error("Failed to write CVAT XML at {path}: {message}")]
CvatWriteError { path: PathBuf, message: String },
#[error("Failed to parse LabelMe JSON from {path}: {source}")]
LabelMeJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write LabelMe JSON to {path}: {source}")]
LabelMeJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Invalid LabelMe dataset layout at {path}: {message}")]
LabelMeLayoutInvalid { path: PathBuf, message: String },
#[error("Failed to parse CreateML JSON from {path}: {source}")]
CreateMlJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Failed to write CreateML JSON to {path}: {source}")]
CreateMlJsonWrite {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Invalid CreateML JSON at {path}: {message}")]
CreateMlJsonInvalid { path: PathBuf, message: String },
#[error("CreateML image not found: {image_ref} (searched from {path})")]
CreateMlImageNotFound { path: PathBuf, image_ref: String },
#[error("Failed to read CreateML image dimensions from {path}: {source}")]
CreateMlImageDimensionRead {
path: PathBuf,
#[source]
source: imagesize::ImageError,
},
#[error("Invalid HF ImageFolder layout at {path}: {message}")]
HfLayoutInvalid { path: PathBuf, message: String },
#[error("Failed to parse HF metadata.jsonl at {path}, line {line}: {message}")]
HfJsonlParse {
path: PathBuf,
line: usize,
message: String,
},
#[error("Failed to write HF metadata.jsonl at {path}: {message}")]
HfWriteError { path: PathBuf, message: String },
#[error("Failed to parse SageMaker Ground Truth manifest at {path}, line {line}: {message}")]
SageMakerManifestParse {
path: PathBuf,
line: usize,
message: String,
},
#[error("Invalid SageMaker Ground Truth manifest at {path}: {message}")]
SageMakerManifestInvalid { path: PathBuf, message: String },
#[error("Failed to write SageMaker Ground Truth manifest at {path}: {message}")]
SageMakerManifestWrite { path: PathBuf, message: String },
#[cfg(feature = "hf-parquet")]
#[error("Failed to parse HF metadata.parquet at {path}: {message}")]
HfParquetParse { path: PathBuf, message: String },
#[cfg(feature = "hf-remote")]
#[error("Invalid HF repo reference '{input}': {message}")]
HfResolveError { input: String, message: String },
#[cfg(feature = "hf-remote")]
#[error("HF Hub API error for {repo_id}: {message}")]
HfApiError { repo_id: String, message: String },
#[cfg(feature = "hf-remote")]
#[error("Failed to download from HF Hub ({repo_id}): {message}")]
HfAcquireError { repo_id: String, message: String },
#[cfg(feature = "hf-remote")]
#[error("Unsupported HF zip payload for {repo_id}: {message}")]
HfZipLayoutInvalid { repo_id: String, message: String },
#[error("Validation failed with {error_count} error(s) and {warning_count} warning(s)")]
ValidationFailed {
error_count: usize,
warning_count: usize,
report: ValidationReport,
},
#[error("Unsupported format: {0}")]
UnsupportedFormat(String),
#[error("Failed to detect format for {path}: {reason}")]
FormatDetectionFailed { path: PathBuf, reason: String },
#[error("Failed to parse JSON while detecting format for {path}: {source}")]
FormatDetectionJsonParse {
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("Lossy conversion from {from} to {to} is blocked — {warning_count} warning(s) found (use --allow-lossy to proceed; see report above)", warning_count = report.warning_count())]
LossyConversionBlocked {
from: String,
to: String,
report: Box<ConversionReport>,
},
#[error("Diff failed: {message}")]
DiffFailed { message: String },
#[error("Sample failed: {message}")]
SampleFailed { message: String },
#[error("Invalid sample parameters: {message}")]
InvalidSampleParams { message: String },
#[error("Failed to write report as JSON: {source}")]
ReportJsonWrite {
#[source]
source: serde_json::Error,
},
}