A framework for elegantly configuring complex applications
—
Comprehensive exception hierarchy for handling configuration errors, instantiation failures, and other Hydra-specific error conditions. These exceptions provide structured error handling and debugging information.
Core exception classes that form the foundation of Hydra's error hierarchy.
class HydraException(Exception):
"""Base exception for all Hydra-specific errors."""
class CompactHydraException(HydraException):
"""Base for exceptions that should display compactly."""Exceptions related to configuration loading, composition, and access.
class MissingConfigException(IOError, ConfigCompositionException):
"""Raised when a required configuration cannot be found."""
def __init__(
self,
message: str,
missing_cfg_file: Optional[str] = None,
options: Optional[Sequence[str]] = None
) -> None:
"""
Parameters:
- message: Error description
- missing_cfg_file: Name of missing config file
- options: Available config options
"""
class ConfigCompositionException(CompactHydraException):
"""Raised when configuration composition fails."""
class SearchPathException(CompactHydraException):
"""Raised when config search path operations fail."""Exceptions related to command-line override parsing and processing.
class OverrideParseException(CompactHydraException):
"""Raised when command-line override parsing fails."""
def __init__(self, override: str, message: str) -> None:
"""
Parameters:
- override: The problematic override string
- message: Error description
"""
super().__init__(message)
self.override = override
self.message = messageExceptions related to object instantiation from configuration.
class InstantiationException(CompactHydraException):
"""Raised when object instantiation fails."""Exceptions for deprecated functionality and version compatibility.
class HydraDeprecationError(HydraException):
"""Raised when deprecated functionality is used inappropriately."""from hydra import compose, initialize
from hydra.errors import MissingConfigException, ConfigCompositionException
try:
with initialize(version_base=None, config_path="conf"):
cfg = compose(config_name="nonexistent_config")
except MissingConfigException as e:
print(f"Config not found: {e}")
if e.missing_cfg_file:
print(f"Missing file: {e.missing_cfg_file}")
if e.options:
print(f"Available options: {e.options}")
# Handle general composition errors
try:
with initialize(version_base=None, config_path="conf"):
cfg = compose(config_name="config", overrides=["invalid_override"])
except ConfigCompositionException as e:
print(f"Composition failed: {e}")from hydra.errors import OverrideParseException
from hydra._internal.core_plugins.basic_sweeper import BasicSweeper
# Simulate override parsing error
try:
# This would typically happen internally during command-line parsing
problematic_override = "key=value=extra_equals"
raise OverrideParseException(
override=problematic_override,
message="Too many equals signs in override"
)
except OverrideParseException as e:
print(f"Override parsing failed: {e.message}")
print(f"Problematic override: {e.override}")from hydra.utils import instantiate
from hydra.errors import InstantiationException
from omegaconf import DictConfig
# Handle instantiation failures
config = DictConfig({
"_target_": "nonexistent.module.Class",
"param": "value"
})
try:
obj = instantiate(config)
except InstantiationException as e:
print(f"Instantiation failed: {e}")
# Could implement fallback logic here
fallback_config = DictConfig({
"_target_": "builtins.dict",
"param": "value"
})
obj = instantiate(fallback_config)from hydra import initialize_config_dir
from hydra.errors import SearchPathException, HydraException
try:
# Invalid config directory
with initialize_config_dir(
version_base=None,
config_dir="/nonexistent/directory"
):
pass
except HydraException as e:
# This might be SearchPathException or another type
print(f"Hydra error: {e}")
if isinstance(e, SearchPathException):
print("Search path specific error")from hydra.errors import HydraDeprecationError
from hydra.types import TargetConf
try:
# This will raise HydraDeprecationError in newer versions
target = TargetConf(_target_="my.module.Class")
except HydraDeprecationError as e:
print(f"Deprecated functionality: {e}")
# Use modern approach instead
from omegaconf import DictConfig
config = DictConfig({"_target_": "my.module.Class"})from hydra import main, compose, initialize
from hydra.errors import (
HydraException,
MissingConfigException,
ConfigCompositionException,
InstantiationException,
OverrideParseException
)
from omegaconf import DictConfig
def safe_config_composition(config_path: str, config_name: str, overrides: list = None):
"""Safely compose configuration with comprehensive error handling."""
if overrides is None:
overrides = []
try:
with initialize(version_base=None, config_path=config_path):
cfg = compose(config_name=config_name, overrides=overrides)
return cfg
except MissingConfigException as e:
print(f"Configuration not found: {e}")
if e.options:
print(f"Available configurations: {', '.join(e.options)}")
return None
except ConfigCompositionException as e:
print(f"Failed to compose configuration: {e}")
return None
except OverrideParseException as e:
print(f"Invalid override '{e.override}': {e.message}")
return None
except HydraException as e:
print(f"Hydra error: {e}")
return None
except Exception as e:
print(f"Unexpected error: {e}")
return None
# Usage
cfg = safe_config_composition("conf", "config", ["db.port=5432"])
if cfg is not None:
print("Configuration loaded successfully")import logging
from hydra.errors import HydraException
from hydra import main
from omegaconf import DictConfig
# Set up logging to capture Hydra errors
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
@main(version_base=None, config_path="conf", config_name="config")
def my_app(cfg: DictConfig) -> None:
try:
# Application logic that might fail
risky_operation(cfg)
except HydraException as e:
logger.error(f"Hydra-specific error: {e}", exc_info=True)
# Could implement retry logic or graceful degradation
except Exception as e:
logger.error(f"Unexpected error: {e}", exc_info=True)
raise
def risky_operation(cfg: DictConfig):
"""Simulate operation that might cause Hydra errors."""
from hydra.utils import instantiate
if "_target_" in cfg:
return instantiate(cfg)
else:
raise ValueError("No _target_ specified")from hydra.errors import HydraException
class AppConfigurationError(HydraException):
"""Application-specific configuration error."""
def __init__(self, message: str, config_section: str = None):
super().__init__(message)
self.config_section = config_section
def validate_config(cfg: DictConfig):
"""Validate configuration and raise custom errors."""
if not cfg.get("database"):
raise AppConfigurationError(
"Database configuration is required",
config_section="database"
)
if cfg.database.port < 1 or cfg.database.port > 65535:
raise AppConfigurationError(
f"Invalid database port: {cfg.database.port}",
config_section="database.port"
)
# Usage with custom error handling
try:
validate_config(cfg)
except AppConfigurationError as e:
print(f"Configuration validation failed: {e}")
if e.config_section:
print(f"Problem in section: {e.config_section}")
except HydraException as e:
print(f"Hydra error: {e}")from hydra.errors import MissingConfigException, InstantiationException
from hydra import initialize, compose
from hydra.utils import instantiate
def robust_app_initialization():
"""Initialize app with fallback configurations."""
configs_to_try = ["prod", "dev", "default"]
for config_name in configs_to_try:
try:
with initialize(version_base=None, config_path="conf"):
cfg = compose(config_name=config_name)
return cfg
except MissingConfigException:
continue
# Last resort: create minimal config
from omegaconf import DictConfig
return DictConfig({"app": {"name": "fallback"}})
def robust_instantiation(config, fallback_target=None):
"""Instantiate with fallback on failure."""
try:
return instantiate(config)
except InstantiationException as e:
print(f"Primary instantiation failed: {e}")
if fallback_target:
try:
fallback_config = {"_target_": fallback_target}
return instantiate(fallback_config)
except InstantiationException:
print("Fallback instantiation also failed")
return NoneInstall with Tessl CLI
npx tessl i tessl/pypi-hydra-core