0
# Error Handling
1
2
Comprehensive exception hierarchy for handling configuration errors, instantiation failures, and other Hydra-specific error conditions. These exceptions provide structured error handling and debugging information.
3
4
## Capabilities
5
6
### Base Exception Classes
7
8
Core exception classes that form the foundation of Hydra's error hierarchy.
9
10
```python { .api }
11
class HydraException(Exception):
12
"""Base exception for all Hydra-specific errors."""
13
14
class CompactHydraException(HydraException):
15
"""Base for exceptions that should display compactly."""
16
```
17
18
### Configuration Exceptions
19
20
Exceptions related to configuration loading, composition, and access.
21
22
```python { .api }
23
class MissingConfigException(IOError, ConfigCompositionException):
24
"""Raised when a required configuration cannot be found."""
25
26
def __init__(
27
self,
28
message: str,
29
missing_cfg_file: Optional[str] = None,
30
options: Optional[Sequence[str]] = None
31
) -> None:
32
"""
33
Parameters:
34
- message: Error description
35
- missing_cfg_file: Name of missing config file
36
- options: Available config options
37
"""
38
39
class ConfigCompositionException(CompactHydraException):
40
"""Raised when configuration composition fails."""
41
42
class SearchPathException(CompactHydraException):
43
"""Raised when config search path operations fail."""
44
```
45
46
### Parsing and Override Exceptions
47
48
Exceptions related to command-line override parsing and processing.
49
50
```python { .api }
51
class OverrideParseException(CompactHydraException):
52
"""Raised when command-line override parsing fails."""
53
54
def __init__(self, override: str, message: str) -> None:
55
"""
56
Parameters:
57
- override: The problematic override string
58
- message: Error description
59
"""
60
super().__init__(message)
61
self.override = override
62
self.message = message
63
```
64
65
### Instantiation Exceptions
66
67
Exceptions related to object instantiation from configuration.
68
69
```python { .api }
70
class InstantiationException(CompactHydraException):
71
"""Raised when object instantiation fails."""
72
```
73
74
### Deprecation Exceptions
75
76
Exceptions for deprecated functionality and version compatibility.
77
78
```python { .api }
79
class HydraDeprecationError(HydraException):
80
"""Raised when deprecated functionality is used inappropriately."""
81
```
82
83
## Usage Examples
84
85
### Configuration Error Handling
86
87
```python
88
from hydra import compose, initialize
89
from hydra.errors import MissingConfigException, ConfigCompositionException
90
91
try:
92
with initialize(version_base=None, config_path="conf"):
93
cfg = compose(config_name="nonexistent_config")
94
except MissingConfigException as e:
95
print(f"Config not found: {e}")
96
if e.missing_cfg_file:
97
print(f"Missing file: {e.missing_cfg_file}")
98
if e.options:
99
print(f"Available options: {e.options}")
100
101
# Handle general composition errors
102
try:
103
with initialize(version_base=None, config_path="conf"):
104
cfg = compose(config_name="config", overrides=["invalid_override"])
105
except ConfigCompositionException as e:
106
print(f"Composition failed: {e}")
107
```
108
109
### Override Parsing Error Handling
110
111
```python
112
from hydra.errors import OverrideParseException
113
from hydra._internal.core_plugins.basic_sweeper import BasicSweeper
114
115
# Simulate override parsing error
116
try:
117
# This would typically happen internally during command-line parsing
118
problematic_override = "key=value=extra_equals"
119
raise OverrideParseException(
120
override=problematic_override,
121
message="Too many equals signs in override"
122
)
123
except OverrideParseException as e:
124
print(f"Override parsing failed: {e.message}")
125
print(f"Problematic override: {e.override}")
126
```
127
128
### Instantiation Error Handling
129
130
```python
131
from hydra.utils import instantiate
132
from hydra.errors import InstantiationException
133
from omegaconf import DictConfig
134
135
# Handle instantiation failures
136
config = DictConfig({
137
"_target_": "nonexistent.module.Class",
138
"param": "value"
139
})
140
141
try:
142
obj = instantiate(config)
143
except InstantiationException as e:
144
print(f"Instantiation failed: {e}")
145
# Could implement fallback logic here
146
fallback_config = DictConfig({
147
"_target_": "builtins.dict",
148
"param": "value"
149
})
150
obj = instantiate(fallback_config)
151
```
152
153
### Search Path Error Handling
154
155
```python
156
from hydra import initialize_config_dir
157
from hydra.errors import SearchPathException, HydraException
158
159
try:
160
# Invalid config directory
161
with initialize_config_dir(
162
version_base=None,
163
config_dir="/nonexistent/directory"
164
):
165
pass
166
except HydraException as e:
167
# This might be SearchPathException or another type
168
print(f"Hydra error: {e}")
169
if isinstance(e, SearchPathException):
170
print("Search path specific error")
171
```
172
173
### Deprecation Error Handling
174
175
```python
176
from hydra.errors import HydraDeprecationError
177
from hydra.types import TargetConf
178
179
try:
180
# This will raise HydraDeprecationError in newer versions
181
target = TargetConf(_target_="my.module.Class")
182
except HydraDeprecationError as e:
183
print(f"Deprecated functionality: {e}")
184
# Use modern approach instead
185
from omegaconf import DictConfig
186
config = DictConfig({"_target_": "my.module.Class"})
187
```
188
189
### Comprehensive Error Handling
190
191
```python
192
from hydra import main, compose, initialize
193
from hydra.errors import (
194
HydraException,
195
MissingConfigException,
196
ConfigCompositionException,
197
InstantiationException,
198
OverrideParseException
199
)
200
from omegaconf import DictConfig
201
202
def safe_config_composition(config_path: str, config_name: str, overrides: list = None):
203
"""Safely compose configuration with comprehensive error handling."""
204
205
if overrides is None:
206
overrides = []
207
208
try:
209
with initialize(version_base=None, config_path=config_path):
210
cfg = compose(config_name=config_name, overrides=overrides)
211
return cfg
212
except MissingConfigException as e:
213
print(f"Configuration not found: {e}")
214
if e.options:
215
print(f"Available configurations: {', '.join(e.options)}")
216
return None
217
except ConfigCompositionException as e:
218
print(f"Failed to compose configuration: {e}")
219
return None
220
except OverrideParseException as e:
221
print(f"Invalid override '{e.override}': {e.message}")
222
return None
223
except HydraException as e:
224
print(f"Hydra error: {e}")
225
return None
226
except Exception as e:
227
print(f"Unexpected error: {e}")
228
return None
229
230
# Usage
231
cfg = safe_config_composition("conf", "config", ["db.port=5432"])
232
if cfg is not None:
233
print("Configuration loaded successfully")
234
```
235
236
### Error Context and Debugging
237
238
```python
239
import logging
240
from hydra.errors import HydraException
241
from hydra import main
242
from omegaconf import DictConfig
243
244
# Set up logging to capture Hydra errors
245
logging.basicConfig(level=logging.DEBUG)
246
logger = logging.getLogger(__name__)
247
248
@main(version_base=None, config_path="conf", config_name="config")
249
def my_app(cfg: DictConfig) -> None:
250
try:
251
# Application logic that might fail
252
risky_operation(cfg)
253
except HydraException as e:
254
logger.error(f"Hydra-specific error: {e}", exc_info=True)
255
# Could implement retry logic or graceful degradation
256
except Exception as e:
257
logger.error(f"Unexpected error: {e}", exc_info=True)
258
raise
259
260
def risky_operation(cfg: DictConfig):
261
"""Simulate operation that might cause Hydra errors."""
262
from hydra.utils import instantiate
263
264
if "_target_" in cfg:
265
return instantiate(cfg)
266
else:
267
raise ValueError("No _target_ specified")
268
```
269
270
### Custom Exception Handling
271
272
```python
273
from hydra.errors import HydraException
274
275
class AppConfigurationError(HydraException):
276
"""Application-specific configuration error."""
277
278
def __init__(self, message: str, config_section: str = None):
279
super().__init__(message)
280
self.config_section = config_section
281
282
def validate_config(cfg: DictConfig):
283
"""Validate configuration and raise custom errors."""
284
285
if not cfg.get("database"):
286
raise AppConfigurationError(
287
"Database configuration is required",
288
config_section="database"
289
)
290
291
if cfg.database.port < 1 or cfg.database.port > 65535:
292
raise AppConfigurationError(
293
f"Invalid database port: {cfg.database.port}",
294
config_section="database.port"
295
)
296
297
# Usage with custom error handling
298
try:
299
validate_config(cfg)
300
except AppConfigurationError as e:
301
print(f"Configuration validation failed: {e}")
302
if e.config_section:
303
print(f"Problem in section: {e.config_section}")
304
except HydraException as e:
305
print(f"Hydra error: {e}")
306
```
307
308
### Error Recovery Patterns
309
310
```python
311
from hydra.errors import MissingConfigException, InstantiationException
312
from hydra import initialize, compose
313
from hydra.utils import instantiate
314
315
def robust_app_initialization():
316
"""Initialize app with fallback configurations."""
317
318
configs_to_try = ["prod", "dev", "default"]
319
320
for config_name in configs_to_try:
321
try:
322
with initialize(version_base=None, config_path="conf"):
323
cfg = compose(config_name=config_name)
324
return cfg
325
except MissingConfigException:
326
continue
327
328
# Last resort: create minimal config
329
from omegaconf import DictConfig
330
return DictConfig({"app": {"name": "fallback"}})
331
332
def robust_instantiation(config, fallback_target=None):
333
"""Instantiate with fallback on failure."""
334
335
try:
336
return instantiate(config)
337
except InstantiationException as e:
338
print(f"Primary instantiation failed: {e}")
339
340
if fallback_target:
341
try:
342
fallback_config = {"_target_": fallback_target}
343
return instantiate(fallback_config)
344
except InstantiationException:
345
print("Fallback instantiation also failed")
346
347
return None
348
```