Error Handling & Troubleshooting
This guide covers every exception AdaptShot can raise, what each one means, and how to fix the underlying problem. It also covers common runtime issues that don't produce exceptions.
Exception Hierarchy
All AdaptShot exceptions inherit from AdaptShotError:
AdaptShotError
├── ConfigValidationError # Invalid configuration
├── InvalidImageError # Image loading/format problems
├── CalibrationNotReadyError # Calibration window not populated
└── BufferCapacityError # Buffer pruning issues
Source: src/adaptshot/utils/exceptions.py
Exception Reference
ConfigValidationError
When: Configuration values violate constraints.
| Error Message |
Cause |
Fix |
"device must be 'cpu'" |
device set to "cuda" or "mps" |
Set device="cpu". v0.1.1 is CPU-first. |
"n_way and k_shot must be positive integers" |
k_shot=0 or n_way=0 |
Set both to positive integers (e.g., n_way=5, k_shot=10). |
"max_buffer_size must be >= 10" |
Buffer too small for meaningful operation |
Set max_buffer_size to at least 10. |
"early_exit_threshold must be within [0.5, 1.0]" |
Threshold outside valid range |
Set a value between 0.5 and 1.0. |
"ece_n_bins must be > 1" |
ECE bins set to 0 or 1 |
Set ece_n_bins to at least 2. |
"calibration_eval_bins must be >= ece_n_bins" |
Eval bins smaller than ECE bins |
Increase calibration_eval_bins or decrease ece_n_bins. |
"ood_threshold_quantile must be in [0.5, 1.0]" |
OOD quantile out of range |
Set between 0.5 and 1.0. |
"ood_absolute_min_distance must be >= 0.0" |
Negative distance threshold |
Set to 0.0 or higher. |
"confidence_weight must be in [0.0, 1.0]" |
Correction weight outside range |
Use a value between 0.0 and 1.0. |
"similarity_metric must be 'cosine' or 'euclidean'" |
Invalid metric name |
Use "cosine" or "euclidean". |
"inference_mode must be 'nearest_neighbor', 'prototypical', or 'contrastive'" |
Invalid mode name |
Use "nearest_neighbor", "prototypical", or "contrastive". |
InvalidImageError
When: Image loading, format, or content fails.
| Error Message Pattern |
Cause |
Fix |
"Image file not found: '{path}'" |
File doesn't exist at given path |
Verify the path is correct and the file exists. Use absolute paths for services. |
"Expected a file path, but got a directory" |
Path points to a directory |
Point to individual image files, not directories. |
"Image format is unreadable or unsupported" |
Corrupted image or unsupported format |
Use PNG or JPEG. Verify the file isn't truncated. |
"Expected 3-channel RGB image, got {N}-channel" |
Grayscale, RGBA, or other channel count |
Convert to RGB: img.convert("RGB") |
"Image dimensions must be positive" |
Zero-size image |
Check the image file isn't empty or corrupted. |
"Failed to extract embedding" |
Backbone failed on valid-looking image |
Verify PyTorch is installed correctly. Check image isn't corrupted internally. |
CalibrationNotReadyError
When: Calibration hasn't accumulated enough observations.
"Calibration window is not ready.
Need at least {min_samples} observations, got {observed}.
Continue collecting feedback with correct()."
Fix: This is expected during early use. Continue calling predict() and correct(). The predict() method handles this internally by falling back to raw confidence. It is safe to ignore for the first ~10-15 predictions.
BufferCapacityError
When: UP-UGF pruning fails to enforce capacity.
"UP-UGF pruning returned inconsistent buffer lengths"
or
"UP-UGF pruning did not enforce max_buffer_size"
Fix: This indicates an internal state inconsistency. Call load_support_images() to rebuild the support set. If it persists, reduce max_buffer_size or check that all embeddings have the same dimensionality.
AdaptShotError (Base)
| Error Message Pattern |
Cause |
Fix |
"FewShotLearner is not initialized" |
Called predict() or correct() before load_support_images() |
Call load_support_images() first. |
"Support set is empty" |
Support set was cleared or never loaded |
Reload support images. |
"Support embeddings must share one dimensionality" |
Mixed backbone outputs (unusual) |
Ensure all support images are the same size and format. |
"State file not found: '{path}'" |
load() called with wrong path |
Verify checkpoint path. Use save() to create a valid checkpoint. |
"Checkpoint integrity check failed" |
Checksums don't match |
Restore from a known-good checkpoint. |
"Failed to load model head" |
Corrupted .head.pt file |
Re-save the checkpoint. |
"Checkpoint is missing required key" |
JSON from an old or corrupted save |
Use a checkpoint created by the current version. |
Common Runtime Issues (No Exceptions)
Issue: Predictions are always wrong
| Possible Cause |
Diagnostic |
Fix |
| Support set too small |
len(learner._sim_embeddings) < 5 |
Add more support images (at least 3-5 per class). |
| Domain mismatch |
Support images look very different from queries |
Support and query images should have similar lighting, background, and resolution. |
| Wrong backbone |
Using mobilenet_v3_small for fine-grained classification |
Switch to resnet18 for higher accuracy. |
Issue: Calibrated confidence is always very low
| Possible Cause |
Diagnostic |
Fix |
| Calibration window not full |
report["current_ece"] near 0 or NaN |
Wait for 10-15 predictions. Calibration improves with more observations. |
| High ECE |
report["current_ece"] > 0.15 |
Change calibration_method to "scaling_binning". Ensure corrections are consistent. |
| Temperature drift |
report["current_temperature"] > 3.0 |
Reduce recalibrate_after_feedback to False to batch updates. |
Issue: Memory usage grows unbounded
| Possible Cause |
Diagnostic |
Fix |
| Buffer exceeds capacity |
len(learner._sim_embeddings) > config.max_buffer_size |
Reduce max_buffer_size. Ensure UP-UGF pruning is running (check for BufferCapacityError warnings). |
| Embedding leaks |
RAM grows even without new predictions |
Restart the process. Embeddings are held in memory by the learner instance. |
| Backbone cache accumulation |
v0.2.0: repeated predictions with different images |
Call learner.clear_backbone_cache() periodically. |
| Possible Cause |
Diagnostic |
Fix |
| Calibration buffer too small |
summary['calibration_size'] < 10 |
Add more calibration data via correct(). LOO mode helps with fewer samples. |
| Alpha too strict |
conformal_alpha=0.01 (99% coverage) |
Relax to conformal_alpha=0.10 or 0.20. |
| Using split mode with tiny buffer |
conformal_mode="split" with < 50 samples |
Switch to conformal_mode="cross". |
Issue: Contrastive mode produces worse results than prototypical
| Possible Cause |
Diagnostic |
Fix |
| Too few support examples |
< 15 per class |
Contrastive mode needs more data; fall back to prototypical. |
| Learning rate too high |
Loss oscillates |
Reduce ContrastiveConfig.learning_rate to 0.001. |
| Not enough epochs |
Loss still decreasing at epoch 50 |
Increase ContrastiveConfig.n_epochs to 100. |
Issue: OOD detection flags too many in-distribution images
| Possible Cause |
Diagnostic |
Fix |
| Shrinkage too aggressive |
Very small support sets (< 5/class) |
Add more support examples per class. |
| Percentile too low |
ood_percentile=90.0 |
Increase to ood_percentile=97.0 or 99.0. |
| Mahalanobis regularization too weak |
Covariance near-singular |
Increase mahalanobis_regularization to 1e-3. |
Issue: Determinism check fails
| Possible Cause |
Diagnostic |
Fix |
| Different PyTorch builds |
pip show torch shows different version |
Use identical PyTorch versions across runs. |
| Non-deterministic CUDA ops |
Running on GPU with cuDNN non-deterministic |
Switch to CPU (device="cpu"). |
| Different seed |
config.seed changed between runs |
Fix seed=42 in both configs. |
Before Reporting a Bug
Run this diagnostic and include the output:
import platform
import torch
import numpy as np
from adaptshot import FewShotLearner
from adaptshot.config.settings import AdaptShotConfig
print(f"Python: {platform.python_version()}")
print(f"PyTorch: {torch.__version__}")
print(f"NumPy: {np.__version__}")
print(f"CPU: {platform.processor()}")
config = AdaptShotConfig(device="cpu", seed=42)
learner = FewShotLearner(config=config)
print(f"Learner: {learner}")
Include:
- The exact error message (copy-paste, don't paraphrase)
- A minimal reproducer script (under 30 lines)
- The output of the diagnostic above
- Your operating system and hardware specs
Verification Checklist
- [ ] You can identify each exception by its error message pattern.
- [ ] You know which exception corresponds to which problem category (config, image, calibration, buffer).
- [ ] You can run the diagnostic script and interpret the output.
- [ ] You understand that
CalibrationNotReadyError is expected in early use and handled internally by predict().
- [ ] You know how to check calibration health via
calibration_report().
MziziGuard-Specific Troubleshooting
App Won't Start
| Symptom |
Cause |
Fix |
ModuleNotFoundError: No module named 'gradio' |
UI dependencies missing |
pip install "adaptshot[ui]" |
ModuleNotFoundError: No module named 'yaml' |
PyYAML missing |
pip install PyYAML |
Address already in use |
Port 7860 occupied |
Use --port 8080 |
config.yaml not found |
Config file missing |
Ensure examples/mziziguard/config.yaml exists |
Model Training Issues
| Symptom |
Cause |
Fix |
| All predictions are same class |
Too few support images |
Increase n_support to 5–10 |
| Confidence always 100% |
Calibration not warmed up |
Make 10+ predictions with corrections |
| "Model not trained" in Diagnose tab |
Skipped Setup tab |
Go to Setup → Generate Samples or Load from Folder |
| Folder loading finds 0 images |
Wrong folder structure |
Use class_name/*.png structure |
OOD Detection Issues
| Symptom |
Cause |
Fix |
| OOD never triggers |
enable_ood_detection: false |
Set to true in config.yaml |
| Everything flagged OOD |
Threshold too aggressive |
Increase ood_threshold_quantile (e.g., 0.99) |
| Non-crop images not caught |
Threshold too permissive |
Decrease ood_absolute_min_distance |
| Symptom |
Cause |
Fix |
| Slow inference (>500ms) |
Heavy backbone + weak CPU |
Switch to mobilenet_v3_small |
| High RAM usage (>300MB) |
Buffer too large |
Reduce max_buffer_size to 50 |
| Battery drain on laptop |
Eco mode disabled |
Set eco_mode: true in config |
| First prediction slow |
Backbone downloading |
Normal — cached after first use |
Quick Diagnostic for MziziGuard
# MziziGuard-specific health check
python -c "
from examples.mziziguard import MziziGuard
guard = MziziGuard()
print(f'Config loaded: {len(guard.known_labels)} diseases')
guard.initialize_with_samples(n_support=3)
print(f'Trained: {guard.is_trained}')
result = guard.diagnose(guard._data_dir + '/healthy_maize_support_00.png')
print(f'Diagnosis works: {result.swahili}')
health = guard.system_health()
print(f'Health report: ECE={health[\"calibration\"][\"ece\"]}')
print('✅ MziziGuard is healthy')
"
Created by Johnson Christopher Hassan
Connect on LinkedIn
Project: github.com/johnson2006christopher/adaptshot