Error Handling Implementation Guide¶
Version: v3.0.10 | Updated: 2026-01-21
Overview¶
CCGO's enhanced error handling system provides:
- User-friendly error messages with actionable hints
- Graceful degradation when optional tools are missing
- Comprehensive configuration validation with helpful suggestions
- Better build failure diagnostics
Architecture¶
src/
├── error.rs # Custom error types and hints
├── config/
│ ├── ccgo_toml.rs # Configuration parsing (enhanced)
│ └── validation.rs # Comprehensive validation
└── utils/
└── tools.rs # Tool detection and validation
Components¶
1. Error Module (src/error.rs)¶
Custom error types with contextual hints:
use crate::error::{CcgoError, hints};
// Configuration errors
CcgoError::config_error_with_hint(
"Invalid package name",
None,
"Package name must be a valid C++ identifier"
)
// Dependency errors
CcgoError::dependency_error_with_hint(
"fmt",
"Invalid version requirement",
"Version requirements support: ^1.0.0, ~1.2.0, >=1.0.0"
)
// Missing tool errors
CcgoError::missing_tool(
"cmake",
"building projects",
hints::cmake() // Provides installation instructions
)
// Build failures with diagnostics
CcgoError::build_failure_with_diagnostics(
"Android",
"NDK not found",
vec!["Check ANDROID_NDK environment variable"],
Some(hints::android_ndk())
)
Available Hints¶
The hints module provides installation instructions for common tools:
hints::cmake()- CMake installationhints::git()- Git installationhints::android_ndk()- Android NDK setuphints::xcode()- Xcode installationhints::visual_studio()- Visual Studio setuphints::mingw()- MinGW installationhints::gradle()- Gradle installationhints::python()- Python installationhints::doxygen()- Doxygen installation
Common Error Patterns¶
// CCGO.toml not found
hints::ccgo_toml_not_found()
// Invalid CCGO.toml
hints::invalid_ccgo_toml()
// Dependency resolution failure
hints::dependency_resolution()
// Build configuration issues
hints::build_config()
// Lockfile out of sync
hints::lockfile_mismatch()
2. Configuration Validation (src/config/validation.rs)¶
Comprehensive validation with helpful error messages:
use crate::config::validate_config;
// Load and validate configuration
let config = CcgoConfig::load()?; // Automatically validates
// Manual validation
validate_config(&config)?;
Validation Checks¶
Package Metadata:
- ✅ Package name (must be valid C++ identifier, not a keyword)
- ✅ Version (must be valid semver: 1.0.0, 2.3.4-alpha.1)
- ✅ License (warns about non-standard SPDX identifiers)
Workspace Configuration: - ✅ Non-empty members list for workspace-only configs - ✅ Valid resolver version ("1" or "2")
Dependencies:
- ✅ At least one valid source (version, git, or path)
- ✅ Valid version requirements (^1.0.0, ~1.2.0, >=1.0.0)
- ✅ Valid git URLs (must start with https://, git://, etc.)
- ✅ No conflicting git refs (can't have both branch and tag)
- ✅ Path dependencies exist (warning only)
Build Configuration: - ✅ Parallel jobs > 0 - ✅ Reasonable job count (warns if > 128)
Platform Configuration:
- ✅ Android minSdk >= 16 (warns if below recommended)
- ✅ Valid iOS version format ("12.0", "14.0")
Binaries and Examples: - ✅ Valid names (C++ identifiers) - ✅ Source files exist (warning only)
3. Tool Detection (src/utils/tools.rs)¶
Detect build tools with graceful degradation:
use crate::utils::tools::{
check_tool,
require_tool,
check_tool_with_requirement,
ToolRequirement,
PlatformTools,
};
// Check if a tool exists
if let Some(tool_info) = check_tool("cmake") {
println!("CMake version: {:?}", tool_info.version);
}
// Require a tool (error if missing)
let cmake = require_tool("cmake", "building projects")?;
// Check with requirement level
check_tool_with_requirement(
"doxygen",
ToolRequirement::Recommended,
"documentation generation"
)?;
// ⚠️ Warns if missing, but continues
Tool Requirement Levels¶
pub enum ToolRequirement {
/// Required - fails with helpful error if missing
Required,
/// Optional - silent if missing
Optional,
/// Recommended - warns if missing, continues
Recommended,
}
Platform-Specific Tool Checking¶
use crate::utils::tools::{
PlatformTools,
check_android_environment,
check_apple_environment,
check_windows_environment,
};
// Check platform-specific tools
let checker = PlatformTools::new("android");
let (required, optional) = checker.check_all()?;
// Android environment
check_android_environment()?; // Checks ANDROID_NDK, ANDROID_HOME
// Apple environment
check_apple_environment()?; // Checks Xcode, command line tools
// Windows environment
check_windows_environment("msvc")?; // Checks MSVC or MinGW
Integration Examples¶
Example 1: Enhanced Build Command¶
use crate::utils::tools::{PlatformTools, ToolRequirement};
use crate::error::CcgoError;
pub fn execute_build(platform: &str) -> Result<()> {
// Check required tools
let checker = PlatformTools::new(platform);
let (required_tools, optional_tools) = checker.check_all()?;
println!("✓ Required tools found:");
for tool in &required_tools {
println!(" • {}: {}", tool.name,
tool.version.as_deref().unwrap_or("installed"));
}
if !optional_tools.is_empty() {
println!("✓ Optional tools found:");
for tool in &optional_tools {
println!(" • {}", tool.name);
}
}
// Proceed with build...
Ok(())
}
Example 2: Enhanced Install Command¶
use crate::error::{CcgoError, hints};
use crate::config::validate_config;
pub fn execute_install(dep_name: Option<&str>) -> Result<()> {
// Load and validate config
let config = CcgoConfig::load()?; // Auto-validates
// Check git is available for git dependencies
let has_git_deps = config.dependencies.iter()
.any(|d| d.git.is_some());
if has_git_deps {
require_tool("git", "installing git dependencies")?;
}
// Install dependencies...
Ok(())
}
Example 3: Better Error Messages¶
Before:
After:
ERROR: Failed to parse CCGO.toml
Common issues:
• Invalid TOML syntax (check quotes, brackets, commas)
• Typo in section names (should be [package] or [workspace])
• Missing closing brackets or quotes
Validate your TOML at: https://www.toml-lint.com/
Before:
After:
ERROR: Invalid version requirement '1.0' for dependency 'fmt'
HINT: Version requirements support:
• Exact: "1.2.3" or "=1.2.3"
• Range: ">=1.0.0, <2.0.0"
• Caret: "^1.0.0" (allows 1.x.x)
• Tilde: "~1.2.0" (allows 1.2.x)
• Wildcard: "1.*" or "1.2.*"
Best Practices¶
1. Always Provide Context¶
// Bad
bail!("Tool not found");
// Good
Err(CcgoError::missing_tool(
"cmake",
"building C++ projects",
hints::cmake()
).into())
2. Use Appropriate Error Types¶
// For configuration errors
CcgoError::config_error_with_hint(message, source, hint)
// For dependency errors
CcgoError::dependency_error_with_hint(dep_name, message, hint)
// For missing tools
CcgoError::missing_tool(tool, required_for, hint)
// For build failures
CcgoError::build_failure_with_diagnostics(platform, message, diagnostics, hint)
3. Validate Early¶
// Validate configuration immediately after loading
let config = CcgoConfig::load()?; // Validates automatically
// Or explicit validation
validate_config(&config)?;
4. Check Tools Before Building¶
// For platform-specific builds
let checker = PlatformTools::new("android");
checker.check_required()?; // Fails fast with helpful errors
// For optional features
check_tool_with_requirement(
"doxygen",
ToolRequirement::Recommended,
"documentation generation"
)?;
Error Message Guidelines¶
When creating error messages:
- Be specific: Say what went wrong and where
- Be actionable: Tell user how to fix it
- Be concise: Keep hints focused on the most likely solution
- Be helpful: Include examples, links, or commands to run
Example:
❌ Bad: "Invalid configuration"
✅ Good:
ERROR: Invalid package name 'class' in CCGO.toml
HINT: Package name 'class' is a C++ reserved keyword.
Choose a different name, e.g., 'class_lib' or 'libclass'
Testing¶
All validation logic includes unit tests:
Current Status¶
✅ Completed: - Custom error types with hints - Comprehensive configuration validation - Tool detection with graceful degradation - Enhanced CCGO.toml parsing errors - Platform-specific tool checking
📝 Integration Tasks (Future):
- Integrate tool checking into build command
- Integrate tool checking into publish command
- Add more platform-specific validations
- Build failure diagnostics with common solutions
Migration Guide¶
To use the new error handling in existing code:
Before:¶
After:¶
use crate::error::{CcgoError, hints};
use crate::utils::tools::require_tool;
// Option 1: Use tool detection
require_tool("cmake", "building projects")?;
// Option 2: Manual error creation
if tool_missing {
return Err(CcgoError::missing_tool(
"cmake",
"building projects",
hints::cmake()
).into());
}