Skip to content

Exceptions

EMBRS defines a hierarchy of custom exceptions rooted at EMBRSError. Catching EMBRSError in your control code lets you handle all EMBRS-specific failures in one place, while the more specific subclasses (ConfigurationError, GridError, WeatherDataError, etc.) allow targeted recovery when you know which operation might fail. Most users will encounter these exceptions when loading configuration files, looking up cells by coordinate, or running ensemble predictions.

Custom exceptions for the EMBRS simulation framework.

This module defines a hierarchy of exceptions used throughout EMBRS to provide clear, specific error messages and enable targeted exception handling by users of the library.

Exception Hierarchy

EMBRSError (base) ├── ConfigurationError - Invalid configuration files or parameters ├── SimulationError - Errors during simulation execution ├── ValidationError - Input validation failures ├── WeatherDataError - Weather data issues ├── ExternalServiceError - External service failures (WindNinja, OpenMeteo) ├── GridError - Grid operations failures ├── FuelModelError - Fuel model lookup or calculation failures └── PredictionError - Fire prediction / ensemble failures

Example

from embrs.exceptions import ConfigurationError raise ConfigurationError("Missing required parameter 'cell_size'")

ConfigurationError

Bases: EMBRSError

Raised when configuration file or parameters are invalid.

This exception is raised when: - Required parameters are missing from config files - Parameter values are out of valid ranges - Config file format is incorrect - Incompatible parameter combinations are specified

Attributes:

Name Type Description
message str

Explanation of the configuration error.

config_path str

Path to the configuration file, if applicable.

parameter str

Name of the problematic parameter, if applicable.

Example

raise ConfigurationError( ... "Start datetime must be before end datetime", ... config_path="/path/to/config.cfg" ... )

Source code in embrs/exceptions.py
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
class ConfigurationError(EMBRSError):
    """Raised when configuration file or parameters are invalid.

    This exception is raised when:
    - Required parameters are missing from config files
    - Parameter values are out of valid ranges
    - Config file format is incorrect
    - Incompatible parameter combinations are specified

    Attributes:
        message (str): Explanation of the configuration error.
        config_path (str): Path to the configuration file, if applicable.
        parameter (str): Name of the problematic parameter, if applicable.

    Example:
        >>> raise ConfigurationError(
        ...     "Start datetime must be before end datetime",
        ...     config_path="/path/to/config.cfg"
        ... )
    """

    def __init__(self, message: str, config_path: Optional[str] = None, parameter: Optional[str] = None):
        self.config_path = config_path
        self.parameter = parameter

        # Build detailed message
        parts = []
        if config_path:
            parts.append(f"in {config_path}")
        if parameter:
            parts.append(f"parameter '{parameter}'")

        if parts:
            full_message = f"{message} ({', '.join(parts)})"
        else:
            full_message = message

        super().__init__(full_message)

EMBRSError

Bases: Exception

Base exception for all EMBRS-related errors.

All custom exceptions in EMBRS inherit from this class, allowing users to catch all EMBRS errors with a single except clause if desired.

Example

try: ... fire.iterate() ... except EMBRSError as e: ... print(f"EMBRS error occurred: {e}")

Source code in embrs/exceptions.py
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class EMBRSError(Exception):
    """Base exception for all EMBRS-related errors.

    All custom exceptions in EMBRS inherit from this class, allowing
    users to catch all EMBRS errors with a single except clause if desired.

    Example:
        >>> try:
        ...     fire.iterate()
        ... except EMBRSError as e:
        ...     print(f"EMBRS error occurred: {e}")
    """

    pass

ExternalServiceError

Bases: EMBRSError

Raised when an external service (WindNinja, OpenMeteo) fails.

This exception is raised when: - WindNinja subprocess fails or times out - OpenMeteo API request fails - Network connectivity issues occur - External service returns invalid data

Attributes:

Name Type Description
message str

Explanation of the service failure.

service str

Name of the external service.

original_error Exception

The underlying exception, if any.

Example

raise ExternalServiceError( ... "WindNinja process timed out after 300 seconds", ... service="WindNinja" ... )

Source code in embrs/exceptions.py
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
class ExternalServiceError(EMBRSError):
    """Raised when an external service (WindNinja, OpenMeteo) fails.

    This exception is raised when:
    - WindNinja subprocess fails or times out
    - OpenMeteo API request fails
    - Network connectivity issues occur
    - External service returns invalid data

    Attributes:
        message (str): Explanation of the service failure.
        service (str): Name of the external service.
        original_error (Exception): The underlying exception, if any.

    Example:
        >>> raise ExternalServiceError(
        ...     "WindNinja process timed out after 300 seconds",
        ...     service="WindNinja"
        ... )
    """

    def __init__(self, message: str, service: Optional[str] = None, original_error: Optional[Exception] = None):
        self.service = service
        self.original_error = original_error

        parts = []
        if service:
            parts.append(f"service: {service}")
        if original_error:
            parts.append(f"caused by: {type(original_error).__name__}: {original_error}")

        if parts:
            full_message = f"{message} ({', '.join(parts)})"
        else:
            full_message = message

        super().__init__(full_message)

FuelModelError

Bases: EMBRSError

Raised when fuel model operations fail.

This exception is raised when: - Invalid fuel model ID is specified - Fuel model data is missing or corrupt - Fuel model calculations fail

Attributes:

Name Type Description
message str

Explanation of the fuel model error.

fuel_model_id int

The fuel model ID involved, if applicable.

Example

raise FuelModelError( ... "Unknown fuel model ID", ... fuel_model_id=999 ... )

Source code in embrs/exceptions.py
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
class FuelModelError(EMBRSError):
    """Raised when fuel model operations fail.

    This exception is raised when:
    - Invalid fuel model ID is specified
    - Fuel model data is missing or corrupt
    - Fuel model calculations fail

    Attributes:
        message (str): Explanation of the fuel model error.
        fuel_model_id (int): The fuel model ID involved, if applicable.

    Example:
        >>> raise FuelModelError(
        ...     "Unknown fuel model ID",
        ...     fuel_model_id=999
        ... )
    """

    def __init__(self, message: str, fuel_model_id: Optional[int] = None):
        self.fuel_model_id = fuel_model_id

        if fuel_model_id is not None:
            full_message = f"{message} (fuel model ID: {fuel_model_id})"
        else:
            full_message = message

        super().__init__(full_message)

GridError

Bases: EMBRSError

Raised when grid operations fail.

This exception is raised when: - Grid coordinates are out of bounds - Cell lookup fails - Grid initialization fails - Neighbor calculations encounter invalid state

Attributes:

Name Type Description
message str

Explanation of the grid error.

row int

Row index involved, if applicable.

col int

Column index involved, if applicable.

Example

raise GridError( ... "Cell coordinates outside grid bounds", ... row=150, ... col=200 ... )

Source code in embrs/exceptions.py
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
class GridError(EMBRSError):
    """Raised when grid operations fail.

    This exception is raised when:
    - Grid coordinates are out of bounds
    - Cell lookup fails
    - Grid initialization fails
    - Neighbor calculations encounter invalid state

    Attributes:
        message (str): Explanation of the grid error.
        row (int): Row index involved, if applicable.
        col (int): Column index involved, if applicable.

    Example:
        >>> raise GridError(
        ...     "Cell coordinates outside grid bounds",
        ...     row=150,
        ...     col=200
        ... )
    """

    def __init__(self, message: str, row: Optional[int] = None, col: Optional[int] = None):
        self.row = row
        self.col = col

        parts = []
        if row is not None:
            parts.append(f"row={row}")
        if col is not None:
            parts.append(f"col={col}")

        if parts:
            full_message = f"{message} ({', '.join(parts)})"
        else:
            full_message = message

        super().__init__(full_message)

PredictionError

Bases: EMBRSError

Raised when fire prediction operations fail.

This exception is raised when: - Ensemble execution fails - Prediction results are invalid - State synchronization fails

Attributes:

Name Type Description
message str

Explanation of the prediction error.

ensemble_member int

The ensemble member that failed, if applicable.

Example

raise PredictionError( ... "Ensemble member failed during parallel execution", ... ensemble_member=5 ... )

Source code in embrs/exceptions.py
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
class PredictionError(EMBRSError):
    """Raised when fire prediction operations fail.

    This exception is raised when:
    - Ensemble execution fails
    - Prediction results are invalid
    - State synchronization fails

    Attributes:
        message (str): Explanation of the prediction error.
        ensemble_member (int): The ensemble member that failed, if applicable.

    Example:
        >>> raise PredictionError(
        ...     "Ensemble member failed during parallel execution",
        ...     ensemble_member=5
        ... )
    """

    def __init__(self, message: str, ensemble_member: Optional[int] = None):
        self.ensemble_member = ensemble_member

        if ensemble_member is not None:
            full_message = f"{message} (ensemble member: {ensemble_member})"
        else:
            full_message = message

        super().__init__(full_message)

SimulationError

Bases: EMBRSError

Raised when an error occurs during simulation execution.

This exception is raised when: - The simulation enters an invalid state - A required resource becomes unavailable - An unrecoverable error occurs during iteration

Attributes:

Name Type Description
message str

Explanation of the simulation error.

sim_time_s float

Simulation time when error occurred, if available.

Example

raise SimulationError( ... "Weather forecast exhausted before simulation end", ... sim_time_s=3600.0 ... )

Source code in embrs/exceptions.py
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
class SimulationError(EMBRSError):
    """Raised when an error occurs during simulation execution.

    This exception is raised when:
    - The simulation enters an invalid state
    - A required resource becomes unavailable
    - An unrecoverable error occurs during iteration

    Attributes:
        message (str): Explanation of the simulation error.
        sim_time_s (float): Simulation time when error occurred, if available.

    Example:
        >>> raise SimulationError(
        ...     "Weather forecast exhausted before simulation end",
        ...     sim_time_s=3600.0
        ... )
    """

    def __init__(self, message: str, sim_time_s: Optional[float] = None):
        self.sim_time_s = sim_time_s

        if sim_time_s is not None:
            full_message = f"{message} (at sim time {sim_time_s:.1f}s)"
        else:
            full_message = message

        super().__init__(full_message)

ValidationError

Bases: EMBRSError

Raised when input validation fails.

This exception is raised when: - Function arguments are invalid - Data structures have invalid contents - Coordinate values are out of bounds

Attributes:

Name Type Description
message str

Explanation of the validation failure.

field str

Name of the field that failed validation, if applicable.

value

The invalid value, if applicable.

Example

raise ValidationError( ... "Fuel moisture must be between 0 and 3", ... field="dead_fuel_moisture", ... value=-0.5 ... )

Source code in embrs/exceptions.py
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
class ValidationError(EMBRSError):
    """Raised when input validation fails.

    This exception is raised when:
    - Function arguments are invalid
    - Data structures have invalid contents
    - Coordinate values are out of bounds

    Attributes:
        message (str): Explanation of the validation failure.
        field (str): Name of the field that failed validation, if applicable.
        value: The invalid value, if applicable.

    Example:
        >>> raise ValidationError(
        ...     "Fuel moisture must be between 0 and 3",
        ...     field="dead_fuel_moisture",
        ...     value=-0.5
        ... )
    """

    def __init__(self, message: str, field: Optional[str] = None, value: object = None):
        self.field = field
        self.value = value

        parts = []
        if field:
            parts.append(f"field '{field}'")
        if value is not None:
            parts.append(f"value={value!r}")

        if parts:
            full_message = f"{message} ({', '.join(parts)})"
        else:
            full_message = message

        super().__init__(full_message)

WeatherDataError

Bases: EMBRSError

Raised when weather data is invalid or unavailable.

This exception is raised when: - Weather file format is incorrect - Weather data is missing required fields - Weather stream is exhausted - Weather values are physically impossible

Attributes:

Name Type Description
message str

Explanation of the weather data error.

source str

Weather data source (file path or 'OpenMeteo').

Example

raise WeatherDataError( ... "Weather stream ended before simulation completion", ... source="OpenMeteo" ... )

Source code in embrs/exceptions.py
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
class WeatherDataError(EMBRSError):
    """Raised when weather data is invalid or unavailable.

    This exception is raised when:
    - Weather file format is incorrect
    - Weather data is missing required fields
    - Weather stream is exhausted
    - Weather values are physically impossible

    Attributes:
        message (str): Explanation of the weather data error.
        source (str): Weather data source (file path or 'OpenMeteo').

    Example:
        >>> raise WeatherDataError(
        ...     "Weather stream ended before simulation completion",
        ...     source="OpenMeteo"
        ... )
    """

    def __init__(self, message: str, source: Optional[str] = None):
        self.source = source

        if source:
            full_message = f"{message} (source: {source})"
        else:
            full_message = message

        super().__init__(full_message)