Unwrap Remediation Quick Reference
Unwrap Remediation Quick Reference
Quick access guide for Week 1 unwrap elimination
Top 20 Files by Critical Unwrap Count
Fix these first - highest crash risk
| # | Critical | High | Total | File | Estimated Time |
|---|---|---|---|---|---|
| 1 | 34 | 0 | 59 | heliosdb-protocols/src/oracle/aq_engine.rs | 1h |
| 2 | 24 | 0 | 28 | heliosdb-compute/src/metadata_cache.rs | 45m |
| 3 | 22 | 0 | 34 | heliosdb-protocols/src/oracle/packages/dbms_aqadm.rs | 45m |
| 4 | 21 | 0 | 52 | heliosdb-protocols/src/oracle/packages/dbms_datapump.rs | 1h |
| 5 | 19 | 0 | 32 | heliosdb-protocols/src/oracle/packages/dbms_lob.rs | 45m |
| 6 | 16 | 0 | 20 | heliosdb-security/src/rls/oracle_policy.rs | 30m |
| 7 | 14 | 2 | 23 | heliosdb-protocols/src/oracle/packages/dbms_sql.rs | 45m |
| 8 | 12 | 1 | 74 | heliosdb-streaming/src/key_management.rs | 1h 30m |
| 9 | 12 | 0 | 24 | heliosdb-protocols/src/oracle/packages/dbms_output.rs | 30m |
| 10 | 12 | 0 | 21 | heliosdb-protocols/src/oracle/packages/utl_file.rs | 30m |
| 11 | 11 | 1 | 21 | heliosdb-protocols/src/oracle/packages/dbms_rls.rs | 30m |
| 12 | 11 | 0 | 26 | heliosdb-protocols/src/oracle/packages/dbms_fga.rs | 45m |
| 13 | 11 | 0 | 19 | heliosdb-protocols/src/oracle/packages/dbms_job.rs | 30m |
| 14 | 11 | 0 | 15 | heliosdb-compute/src/cache_invalidation.rs | 30m |
| 15 | 10 | 0 | 10 | heliosdb-protocols/src/oracle/packages/dbms_scheduler.rs | 20m |
| 16 | 8 | 0 | 8 | heliosdb-compute/src/query_coordinator.rs | 15m |
| 17 | 7 | 0 | 8 | heliosdb-compute/src/tracking.rs | 15m |
| 18 | 7 | 0 | 7 | heliosdb-protocols/src/oracle/packages/dbms_random.rs | 15m |
| 19 | 6 | 0 | 6 | heliosdb-protocols/src/oracle/packages/dbms_stats.rs | 15m |
| 20 | 5 | 0 | 5 | heliosdb-protocols/src/oracle/packages/dbms_session.rs | 10m |
Top 20 Total: 263 critical unwraps (~79% of all critical unwraps) Estimated Time: ~12 hours
Common Pattern Fixes
1. Lock Unwraps (284 total - MOST COMMON)
Before (Dangerous):
let mut sessions = self.sessions.write().unwrap();let data = self.cache.lock().unwrap();let guard = self.state.read().unwrap();After (Safe):
let mut sessions = self.sessions.write() .map_err(|e| Error::LockPoisoned("sessions"))?;
let data = self.cache.lock() .map_err(|e| Error::LockPoisoned("cache"))?;
let guard = self.state.read() .map_err(|e| Error::LockPoisoned("state"))?;Best (parking_lot - No unwrap needed):
// Add to Cargo.toml: parking_lot = "0.12"use parking_lot::{RwLock, Mutex};
// Direct access, never failslet mut sessions = self.sessions.write();let data = self.cache.lock();let guard = self.state.read();Files affected: 25+ files across protocols, compute, streaming
2. I/O Operations (35 total)
Before (Data loss risk):
file.read_exact(&mut buffer).unwrap();writer.write_all(&data).unwrap();fs::create_dir_all(&path).unwrap();After (Recoverable):
file.read_exact(&mut buffer) .map_err(|e| StorageError::ReadFailed { path: path.clone(), source: e })?;
writer.write_all(&data) .map_err(|e| StorageError::WriteFailed { path: path.clone(), source: e })?;
fs::create_dir_all(&path) .map_err(|e| StorageError::CreateDirFailed { path: path.clone(), source: e })?;Files affected: heliosdb-storage (SSTable, WAL, compaction)
3. Array/Collection Access (12 total)
Before (Index panic):
let first = items.first().unwrap();let last = results.last().unwrap();let value = buckets[0].unwrap();After (Safe with context):
let first = items.first() .ok_or(Error::EmptyCollection("items"))?;
let last = results.last() .ok_or(Error::NoResults)?;
let value = buckets.get(0) .ok_or(Error::InvalidBucketIndex(0))?;Files affected:
- heliosdb-storage/src/sstable/reader.rs
- heliosdb-compute/src/optimizer.rs
- heliosdb-compute/src/online_aggregation.rs
4. Parse Operations (161 total)
Before (Panic on invalid input):
let num = s.parse::<u64>().unwrap();let json = serde_json::from_str(&data).unwrap();let addr = SocketAddr::from_str(&s).unwrap();After (Descriptive errors):
let num = s.parse::<u64>() .map_err(|e| ParseError::InvalidInteger { input: s.to_string(), source: e })?;
let json = serde_json::from_str(&data) .map_err(|e| ParseError::InvalidJson { data: truncate(&data, 100), source: e })?;
let addr = SocketAddr::from_str(&s) .map_err(|e| ParseError::InvalidSocketAddr { input: s.to_string(), source: e })?;Files affected: Protocol parsers, configuration, SQL engines
5. HashMap Access (30 total)
Before (Panic on missing key):
let value = map.get(&key).unwrap();let entry = cache.remove(&id).unwrap();After (Explicit key not found):
let value = map.get(&key) .ok_or_else(|| Error::KeyNotFound { key: key.clone() })?;
let entry = cache.remove(&id) .ok_or_else(|| Error::CacheEntryNotFound { id: id.clone() })?;Files affected: Various caches, state managers
6. SystemTime Operations (Rare but critical)
Before (Can panic on time going backwards):
let ts = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap() .as_secs();After (Handles time anomalies):
let ts = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap_or_else(|_| { warn!("System time before UNIX_EPOCH, using 0"); Duration::from_secs(0) }) .as_secs();Files affected:
- heliosdb-streaming/src/key_management.rs (3 instances)
Day-by-Day Plan
Day 2: Lock Unwraps (6 hours)
Goal: Eliminate 204 lock unwraps in heliosdb-protocols
Files (in order):
- oracle/aq_engine.rs (34 critical)
- oracle/packages/dbms_datapump.rs (21 critical)
- oracle/packages/dbms_aqadm.rs (22 critical)
- oracle/packages/dbms_lob.rs (19 critical)
- oracle/packages/dbms_sql.rs (14 critical)
- oracle/packages/dbms_output.rs (12 critical)
- oracle/packages/utl_file.rs (12 critical)
- oracle/packages/dbms_rls.rs (11 critical)
- oracle/packages/dbms_fga.rs (11 critical)
- oracle/packages/dbms_job.rs (11 critical)
Remaining Oracle packages: dbms_scheduler, dbms_random, dbms_stats, etc.
Day 3: Compute + Streaming Locks (4 hours)
Goal: Eliminate 64 lock unwraps
heliosdb-compute:
- metadata_cache.rs (24 critical) ⭐ Hot path
- cache_invalidation.rs (11 critical)
- query_coordinator.rs (8 critical)
- tracking.rs (7 critical)
heliosdb-streaming:
- key_management.rs (12 critical) ⭐ Includes SystemTime
Day 4: I/O Operations (4 hours)
Goal: Eliminate 35 I/O unwraps in heliosdb-storage
Focus areas:
- SSTable reader (hot read path)
- WAL operations (crash safety)
- Compaction (background operations)
Day 5: Parse Operations (5 hours)
Goal: Eliminate 161 parse unwraps
By crate:
- heliosdb-protocols: 79 unwraps
- heliosdb-security: 40 unwraps (JWT parsing)
- heliosdb-streaming: 23 unwraps
- heliosdb-storage: 16 unwraps
Day 6: Array + HashMap (3 hours)
Goal: Eliminate 42 unwraps
- Array access: 12 unwraps
- HashMap access: 30 unwraps
Day 7: Validation + Testing (6 hours)
Goal: Verify all changes
- Top medium-priority files (3 hours)
- Full test suite (1 hour)
- Performance benchmarks (1 hour)
- Manual testing (1 hour)
Testing After Each Fix
# Run tests for specific cratecd heliosdb-protocolscargo test --lib
# Run integration testscargo test --test '*'
# Check for remaining unwrapsrg '\.unwrap\(\)' src/ --type rust | grep -v '/tests/'
# Performance checkcargo benchError Type Examples
Add to each crate’s error.rs:
#[derive(Debug, thiserror::Error)]pub enum Error { #[error("Lock poisoned: {resource}")] LockPoisoned { resource: &'static str },
#[error("I/O error on {path}: {source}")] IoError { path: PathBuf, #[source] source: std::io::Error },
#[error("Parse error for {field}: expected {expected_type}, got '{value}'")] ParseError { field: &'static str, expected_type: &'static str, value: String, #[source] source: Box<dyn std::error::Error + Send + Sync>, },
#[error("Array access error: {context}")] ArrayAccessError { context: String },
#[error("Key not found: {key}")] KeyNotFound { key: String },}Verification Commands
Check remaining unwraps:
# Production code onlyfind heliosdb-*/src -name "*.rs" | \ grep -v "/tests/" | \ xargs rg '\.unwrap\(\)' | wc -l
# By cratefor crate in heliosdb-*; do count=$(find $crate/src -name "*.rs" 2>/dev/null | \ grep -v "/tests/" | \ xargs rg '\.unwrap\(\)' 2>/dev/null | wc -l) if [ $count -gt 0 ]; then echo "$crate: $count" fidone | sort -t: -k2 -rnCheck for new unwraps:
# Git diff since last commitgit diff HEAD~1 | rg '^\+.*\.unwrap\(\)'Progress Dashboard
Track progress in this format:
WEEK 1 UNWRAP ELIMINATION PROGRESS
Day 2: Lock Unwraps[████████████████████--------] 204/204 (100%)Files: 25/25 ✓Tests: ✓ PassingBenchmarks: ✓ No regression
Day 3: Compute + Streaming[████████████████████--------] 52/64 (81%)Files: 4/5 ✓Tests: ✓ PassingCurrent: streaming/key_management.rs
Day 4: I/O Operations[░░░░░░░░░░░░░░░░░░░░--------] 0/35 (0%)Status: Not started
...Common Mistakes to Avoid
❌ Don’t just replace with expect():
// Still panics!let data = self.state.read().expect("Failed to acquire lock");❌ Don’t use generic error messages:
// Not helpful for debugging.map_err(|e| Error::Generic(e.to_string()))?❌ Don’t ignore lock poisoning:
// Hides the real problemlet data = self.state.read().unwrap_or_else(|e| e.into_inner());Do provide context:
let data = self.state.read() .map_err(|e| Error::LockPoisoned { resource: "query_state", operation: "read_lock", context: "processing SELECT query" })?;Resources
- Full analysis:
/home/claude/HeliosDB/docs/UNWRAP_ANALYSIS_WEEK1.md - Rust error handling: https://doc.rust-lang.org/book/ch09-00-error-handling.html
- parking_lot docs: https://docs.rs/parking_lot/
- thiserror docs: https://docs.rs/thiserror/
Quick Reference - Updated 2025-11-09