Skip to content

How to handle simulation errors

This page covers error handling in the simulation module, including parsing EnergyPlus error reports and handling simulation failures.

Python only, permanently

Running a locally installed EnergyPlus and reading its results belongs to Python alone. JavaScript is not waiting on a port and will not gain a counterpart: this is a permanent boundary, so no issue tracks it, and moving the capability out of that state takes a constitutional amendment rather than a ledger edit.

Requires an EnergyPlus installation on the machine and a subprocess to drive it, then reads the eplusout files that run leaves on disk. Neither the installation nor the subprocess is available in a browser, which is the runtime the JavaScript library targets. JavaScript reaches EnergyPlus by the other mechanism instead: see browser-simulation, which is not a workaround for this entry but a different capability.

The full entry, including the vocabulary this capability owns, is on the capability parity page.

Error Report

The ErrorReport class parses the .err file produced by EnergyPlus:

from idfkit.simulation import simulate

result = simulate(model, weather)

# Access the error report
errors = result.errors

# Check for problems
if errors.has_fatal:
    print("Simulation had fatal errors")
if errors.has_severe:
    print("Simulation had severe errors")
if errors.warning_count > 0:
    print(f"Simulation had {errors.warning_count} warnings")

Error Severity Levels

EnergyPlus uses several error severity levels:

Level Description Effect
Fatal Unrecoverable error Simulation stops immediately
Severe Serious problem May cause incorrect results
Warning Potential issue Simulation continues
Info Informational No action needed

Querying Errors

By Severity

errors = result.errors

# Fatal errors (simulation stopped)
for err in errors.fatal:
    print(f"FATAL: {err.message}")

# Severe errors (may cause incorrect results)
for err in errors.severe:
    print(f"SEVERE: {err.message}")

# Warnings
for warn in errors.warnings:
    print(f"Warning: {warn.message}")

Error Counts

print(f"Fatal: {errors.fatal_count}")
print(f"Severe: {errors.severe_count}")
print(f"Warnings: {errors.warning_count}")

Summary

# Get a formatted summary string
print(errors.summary())
# Output: "0 Fatal, 2 Severe, 15 Warnings"

ErrorMessage Attributes

Each error/warning is an ErrorMessage object:

Every field of ErrorMessage, with its type and its default, is in the API reference. It is generated from the source, so it cannot fall behind the way the table that used to sit here did.

Simulation Exceptions

The simulate() function raises SimulationError for certain failures:

from idfkit.exceptions import SimulationError

try:
    result = simulate(model, weather)
except SimulationError as e:
    print(f"Simulation failed: {e}")
    print(f"Exit code: {e.exit_code}")
    print(f"Stderr: {e.stderr}")

Exception Cases

Situation Exception
Weather file not found SimulationError
EnergyPlus not found EnergyPlusNotFoundError
Timeout exceeded SimulationError (exit_code=None)
OS error starting process SimulationError
Model version differs from installed EnergyPlus VersionMismatchError

Version Mismatch

By default simulate() refuses to run when model.version doesn't match the installed EnergyPlus version, raising VersionMismatchError with a suggested migration chain. Two ways to resolve it:

# Option A: let simulate() forward-migrate transparently
result = simulate(model, weather, auto_migrate=True)
print(result.migration_report.summary())

# Option B: migrate explicitly first, inspect the report, then simulate
from idfkit import migrate
report = migrate(model, target_version=(25, 2, 0))
result = simulate(report.migrated_model, weather)

Backward migration (installed EnergyPlus older than the model) is never attempted and always raises. See how to migrate models between versions.

Timeout Handling

try:
    result = simulate(model, weather, timeout=60.0)
except SimulationError as e:
    if e.exit_code is None:
        print("Simulation timed out")
    else:
        print(f"Simulation failed with exit code {e.exit_code}")

Non-Exception Failures

Some simulation failures don't raise exceptions but return a result with success=False:

result = simulate(model, weather)

if not result.success:
    print(f"Exit code: {result.exit_code}")

    # Check errors
    if result.errors.has_fatal:
        for err in result.errors.fatal:
            print(f"Fatal: {err.message}")

Batch Error Handling

In batch processing, individual failures don't stop the batch:

from idfkit.simulation import simulate_batch

batch = simulate_batch(jobs)

# Check overall success
if not batch.all_succeeded:
    print(f"{len(batch.failed)} jobs failed")

# Handle failures individually
for i, result in enumerate(batch):
    if not result.success:
        print(f"Job {i} failed:")
        for err in result.errors.fatal:
            print(f"  {err.message}")

Common EnergyPlus Errors

Missing Required Input

** Severe  ** GetSurfaceData: BuildingSurface:Detailed="WALL_1", Construction="EXTERIOR_WALL" was not found.

Solution: Ensure all referenced objects exist in the model.

Invalid Weather Data

** Fatal  ** GetWeatherDataPeriods: Weather file has no data for requested period

Solution: Check that run period dates match weather file coverage.

Geometry Errors

** Severe  ** GetSurfaceData: Surface="WALL_1" has zero or negative area

Solution: Fix surface vertex coordinates.

Schedule Errors

** Severe  ** GetSchedule: Schedule="OCCUPANCY" was not found

Solution: Add the missing schedule or fix the reference.

HVAC Sizing

** Severe  ** Sizing:Zone: Zone="ZONE_1" has zero volume

Solution: Ensure zone geometry is properly enclosed.

Debugging Tips

1. Check the Error Report First

if not result.success:
    print(errors.summary())
    for err in errors.fatal + errors.severe:
        print(err.message)

2. Examine Raw Output

# Check stderr
print(result.stderr)

# Check the run directory
print(f"Outputs in: {result.run_dir}")

3. Run Design-Day First

Design-day simulations are faster and catch most errors:

# Quick validation
result = simulate(model, weather, design_day=True)
if result.success:
    # Then run full annual
    result = simulate(model, weather, annual=True)

4. Validate Before Simulation

from idfkit import validate_document

validation = validate_document(model)
if not validation.is_valid:
    for err in validation.errors:
        print(err)

Error Report from File

Parse an error file directly:

from idfkit.simulation import ErrorReport

errors = ErrorReport.from_file("/path/to/eplusout.err")
print(errors.summary())

Or from string:

err_text = Path("eplusout.err").read_text()
errors = ErrorReport.from_string(err_text)

See Also