Skip to content

CBA workflow silently continues even if rolling horizon optimization fails when using HiGHS #760

Description

@measrainsey

Version Checks

  • This bug exists on the latest release of Open-TYNDP.
  • This bug exists on the current master branch of Open-TYNDP.
  • This bug does NOT exist in the upstream master branch of PyPSA-Eur (therefore, the bug is likely Open-TYNDP specific).

Affected Component/Workflow

  • I have labeled this bug report with the affected component(s) using GitHub labels (e.g., SB, CBA, documentation, etc.).

Change Classification

Standard

Security & Data Risk Check

  • This bug touches or exposes confidential data.
  • This bug adds or changes external data sources, download URLs, APIs, services, credentials, or tokens.
  • This bug could affect data integrity or reproducibility of published results.

Risk Level of Fix

N/A

Bug Description

When using HiGHS as the solver for the rolling horizon optimization within the CBA, if one of the rolling horizon (RH) windows fails due to infeasibility, the workflow doesn't crash and instead continues until the last rule. In contrast, when using Gurobi as the solver, if a RH optimization fails, the workflow will crash.

Additionally, the workflow even goes on to save failed optimization as a network.

We shouldn't allow the workflow to silently fail like this, as it gives the impression that the optimization was feasible for the project/reference network.

For example, here is a project whose rolling horizon optimization failed:

 92%|█████████▏| 49/53 [31:05<02:29, 37.46s/it]INFO:__main__:Optimizing network for snapshot horizon [2009-12-07 23:00:00:2009-12-14 22:00:00] (50/53).
WARNING:pypsa.optimization.constraints:Stores ['BE00 battery', 'DKW1 battery', 'FR00 battery', 'GB00 battery', 'GBNI battery', 'IE00 battery', 'LV00 battery', 'NL00 battery']: Cyclic energy level constraint overrules initial value setting. User-defined e_initial will be ignored.
/scratch/htc-panfs/mmeng/open-tyndp/.pixi/envs/open-tyndp/lib/python3.12/site-packages/pypsa/optimization/optimize.py:566: FutureWarning: Passing an int for `transmission_losses` is deprecated and will be removed in PyPSA 2.0. Explicitly pass {'mode': 'tangents', 'segments': 2} (current behavior) or use the new secant-based losses via `transmission_losses=True`.
  m = n.optimize.create_model(
INFO:linopy.model: Solve problem using Highs solver
INFO:linopy.model:Solver logs written to `results/tyndp/NT/logs/cba/projects/project_t4_2030_solver.log`.
INFO:linopy.model:Solver options:
 - solver: simplex
 - parallel: off
 - primal_feasibility_tolerance: 1e-06
 - dual_feasibility_tolerance: 1e-06
 - random_seed: 123
Running HiGHS 1.14.0 (git hash: n/a): Copyright (c) 2026 under MIT licence terms
INFO:linopy.solvers:Log file at /scratch/htc-panfs/mmeng/open-tyndp/results/tyndp/NT/logs/cba/projects/project_t4_2030_solver.log
LP has 783098 rows; 397320 cols; 1391514 nonzeros
Coefficient ranges:
  Matrix  [1e-02, 1e+00]
  Cost    [9e-03, 1e+05]
  Bound   [9e-01, 5e+03]
  RHS     [1e-02, 2e+09]
WARNING: Problem has some excessively large row bounds
WARNING:    Consider scaling the    bounds by 1e-4, or setting the user_bound_scale option to -12
Presolving model
60590 rows, 295407 cols, 557750 nonzeros 0s
39503 rows, 245157 cols, 409806 nonzeros 2s
Dependent equations search running on 34515 equations with time limit of 1000.00s
Dependent equations search removed 0 rows and 0 nonzeros in 0.01s (limit = 1000.00s)
34769 rows, 235418 cols, 395000 nonzeros 14s
Presolve reductions: rows 34769(-748329); columns 235418(-161902); nonzeros 395000(-996514) 
Solving the presolved LP
Using dual simplex solver
  Iteration        Objective     Infeasibilities num(sum)
          0     0.0000000000e+00 Ph1: 0(0) 15.0s
      25577     1.1093422913e+10 16.0s
Model status        : Infeasible
Simplex   iterations: 25577
Objective value     :  1.1159740885e+10
HiGHS run time      :         16.00
WARNING:linopy.constants:Optimization potentially failed: 
Status: warning
Termination condition: infeasible
Solution: 0 primals, 0 duals
Objective: nan
Solver model: available
Solver message: Infeasible

WARNING:__main__:Optimization failed with status warning and condition infeasible
WARNING:__main__:Fallback also failed: warning / infeasible

 92%|█████████▏| 49/53 [31:27<02:34, 38.53s/it]
WARNING:__main__:Solving status 'warning' with termination condition 'infeasible'
INFO:__main__:Maximum memory usage: (9230.265625, 1781882316.1444426)
INFO:pypsa.network.io:Exported network 'PyPSA-Eur (tyndp)' saved to 'results/tyndp/NT/cba/networks/project_t4_2030.nc contains: storage_units, buses, loads, global_constraints, stores, generators, links, shapes, carriers
[Fri Jun 19 17:21:01 2026]
Finished jobid: 0 (Rule: solve_cba_network)
1 of 1 steps (100%) done
Storing output in storage.

Actual Behavior

Instead of failing due to infeasibilities, the entire DAG/workflow completes:

[Fri Jun 19 16:48:41 2026]
rule solve_cba_network:
    input: resources/tyndp/NT/cba/networks/project_t4_2030.nc
    output: results/tyndp/NT/cba/networks/project_t4_2030.nc
    log: results/tyndp/NT/logs/cba/projects/project_t4_2030_solver.log, results/tyndp/NT/logs/cba/projects/project_t4_2030_memory.log, results/tyndp/NT/logs/cba/projects/project_t4_2030_python.log
    jobid: 125
    reason: Missing output files: results/tyndp/NT/cba/networks/project_t4_2030.nc; Updated input files: resources/tyndp/NT/cba/networks/project_t4_2030.nc
    wildcards: run=NT, cba_project=t4, planning_horizons=2030
    resources: mem_mb=40000, mem_mib=38147, disk_mb=8000, disk_mib=7630, tmpdir=<TBD>, runtime=60, partition=big
Submitted job 125 with external jobid 'Submitted batch job 1251594'.
Select jobs to execute...
Execute 1 jobs...

[Fri Jun 19 16:48:51 2026]
rule solve_cba_reference_network:
    input: resources/tyndp/NT/cba/networks/rl_2030.nc
    output: results/tyndp/NT/cba/networks/reference_2030.nc
    log: results/tyndp/NT/logs/cba/reference/reference_2030_solver.log, results/tyndp/NT/logs/cba/reference/reference_2030_memory.log, results/tyndp/NT/logs/cba/reference/reference_2030_python.log
    jobid: 10
    reason: Missing output files: results/tyndp/NT/cba/networks/reference_2030.nc; Updated input files: resources/tyndp/NT/cba/networks/rl_2030.nc
    wildcards: run=NT, planning_horizons=2030
    resources: mem_mb=40000, mem_mib=38147, disk_mb=8000, disk_mib=7630, tmpdir=<TBD>, runtime=60, partition=big
Submitted job 10 with external jobid 'Submitted batch job 1251595'.
Select jobs to execute...
Execute 1 jobs...

[Fri Jun 19 16:49:01 2026]
rule solve_cba_network:
    input: resources/tyndp/NT/cba/networks/project_t16_2030.nc
    output: results/tyndp/NT/cba/networks/project_t16_2030.nc
    log: results/tyndp/NT/logs/cba/projects/project_t16_2030_solver.log, results/tyndp/NT/logs/cba/projects/project_t16_2030_memory.log, results/tyndp/NT/logs/cba/projects/project_t16_2030_python.log
    jobid: 130
    reason: Missing output files: results/tyndp/NT/cba/networks/project_t16_2030.nc; Params have changed since last execution: Union of exclusive params before and now across all output: before: {'horizon': 168, 'overlap': 1, 'options': {'noisy_costs': False, 'load_shedding': {'enable': True, 'apply_to_all_carriers': True}, 'io_api': 'direct', 'include_objective_constant': False}, 'solver': {'name': 'gurobi', 'options': 'gurobi-simplex'}, 'solver_options': {'highs-simplex': {'parallel': 'off'}, 'gurobi-simplex': {'FeasibilityTol': 1e-06, 'OptimalityTol': 1e-06}}, 'partition': 'big', 'mem_mb': 40000, 'runtime': '1h'} now: {'horizon': 168, 'overlap': 1, 'options': {'noisy_costs': False, 'load_shedding': {'enable': True, 'apply_to_all_carriers': True}, 'io_api': 'direct', 'include_objective_constant': False}, 'solver': {'name': 'highs', 'options': 'highs-simplex'}, 'solver_options': {'highs-simplex': {'parallel': 'off', 'primal_feasibility_tolerance': 1e-06, 'dual_feasibility_tolerance': 1e-06}}, 'partition': 'big', 'mem_mb': 40000, 'runtime': '1h'}
    wildcards: run=NT, cba_project=t16, planning_horizons=2030
    resources: mem_mb=40000, mem_mib=38147, disk_mb=8000, disk_mib=7630, tmpdir=<TBD>, runtime=60, partition=big
Submitted job 130 with external jobid 'Submitted batch job 1251596'.
[Fri Jun 19 17:21:03 2026]
Finished jobid: 125 (Rule: solve_cba_network)
1 of 11 steps (9%) done
Removing temporary output resources/tyndp/NT/cba/networks/project_t4_2030.nc.
[Fri Jun 19 17:22:43 2026]
Finished jobid: 10 (Rule: solve_cba_reference_network)
2 of 11 steps (18%) done
Select jobs to execute...
Execute 1 jobs...

[Fri Jun 19 17:22:43 2026]
rule make_indicators:
    input: results/tyndp/NT/cba/networks/reference_2030.nc, results/tyndp/NT/cba/networks/project_t4_2030.nc, data/tyndp_cba_non_co2_emissions/archive/2024/a.3_non-co2-emissions.csv, resources/tyndp/NT/cba/tyndp_indicators.csv, resources/tyndp/NT/cba/cba_project_methods.csv
    output: results/tyndp/NT/cba/project_t4_2030.csv
    jobid: 9
    reason: Input files updated by another job: results/tyndp/NT/cba/networks/project_t4_2030.nc, results/tyndp/NT/cba/networks/reference_2030.nc
    wildcards: run=NT, cba_project=t4, planning_horizons=2030
    resources: mem_mb=40000, mem_mib=38147, disk_mb=8000, disk_mib=7630, tmpdir=<TBD>, runtime=60, partition=big
Submitted job 9 with external jobid 'Submitted batch job 1252042'.
[Fri Jun 19 17:23:13 2026]
Finished jobid: 9 (Rule: make_indicators)
3 of 11 steps (27%) done
Select jobs to execute...
Execute 1 jobs...

[Fri Jun 19 17:23:13 2026]
rule plot_cba_benchmark:
    input: results/tyndp/NT/cba/project_t4_2030.csv
    output: results/tyndp/NT/cba/validation_2030/project_t4_2030.png
    jobid: 132
    reason: Missing output files: results/tyndp/NT/cba/validation_2030/project_t4_2030.png; Input files updated by another job: results/tyndp/NT/cba/project_t4_2030.csv
    wildcards: run=NT, planning_horizons=2030, cba_project=t4
    resources: mem_mb=40000, mem_mib=38147, disk_mb=8000, disk_mib=7630, tmpdir=<TBD>, runtime=60, partition=big
Submitted job 132 with external jobid 'Submitted batch job 1252043'.
[Fri Jun 19 17:23:33 2026]
Finished jobid: 130 (Rule: solve_cba_network)
4 of 11 steps (36%) done
Removing temporary output resources/tyndp/NT/cba/networks/project_t16_2030.nc.
Select jobs to execute...
Execute 1 jobs...

[Fri Jun 19 17:23:33 2026]
rule make_indicators:
    input: results/tyndp/NT/cba/networks/reference_2030.nc, results/tyndp/NT/cba/networks/project_t16_2030.nc, data/tyndp_cba_non_co2_emissions/archive/2024/a.3_non-co2-emissions.csv, resources/tyndp/NT/cba/tyndp_indicators.csv, resources/tyndp/NT/cba/cba_project_methods.csv
    output: results/tyndp/NT/cba/project_t16_2030.csv
    jobid: 129
    reason: Missing output files: results/tyndp/NT/cba/project_t16_2030.csv; Input files updated by another job: results/tyndp/NT/cba/networks/project_t16_2030.nc, results/tyndp/NT/cba/networks/reference_2030.nc
    wildcards: run=NT, cba_project=t16, planning_horizons=2030
    resources: mem_mb=40000, mem_mib=38147, disk_mb=8000, disk_mib=7630, tmpdir=<TBD>, runtime=60, partition=big
Submitted job 129 with external jobid 'Submitted batch job 1252044'.
[Fri Jun 19 17:23:33 2026]
Finished jobid: 132 (Rule: plot_cba_benchmark)
5 of 11 steps (45%) done
[Fri Jun 19 17:24:03 2026]
Finished jobid: 129 (Rule: make_indicators)
6 of 11 steps (55%) done
Select jobs to execute...
Execute 1 jobs...

[Fri Jun 19 17:24:03 2026]
rule collect_indicators:
[Fri Jun 19 17:24:24 2026]
rule plot_indicators:
    input: results/tyndp/NT/cba/indicators_2030.csv, resources/tyndp/NT/cba/transmission_projects.csv
    output: results/tyndp/NT/cba/plots_2030
    jobid: 7
    reason: Missing output files: results/tyndp/NT/cba/plots_2030; Input files updated by another job: results/tyndp/NT/cba/indicators_2030.csv

[Fri Jun 19 17:24:24 2026]
rule plot_indicators:
    input: results/tyndp/NT/cba/indicators_2030.csv, resources/tyndp/NT/cba/transmission_projects.csv
    output: results/tyndp/NT/cba/plots_2030
    jobid: 7
    reason: Missing output files: results/tyndp/NT/cba/plots_2030; Input files updated by another job: results/tyndp/NT/cba/indicators_2030.csv
    wildcards: run=NT, planning_horizons=2030
    resources: mem_mb=40000, mem_mib=38147, disk_mb=8000, disk_mib=7630, tmpdir=<TBD>, runtime=60, partition=big
Submitted job 7 with external jobid 'Submitted batch job 1252048'.
[Fri Jun 19 17:24:33 2026]
Finished jobid: 133 (Rule: plot_cba_benchmark)
8 of 11 steps (73%) done
[Fri Jun 19 17:24:43 2026]
Finished jobid: 7 (Rule: plot_indicators)
9 of 11 steps (82%) done
Select jobs to execute...
Execute 1 jobs...

[Fri Jun 19 17:24:43 2026]
localrule collect_cba_scenario:
    input: results/tyndp/NT/cba/plots_2030, results/tyndp/NT/cba/validation_2030/project_t4_2030.png, results/tyndp/NT/cba/validation_2030/project_t16_2030.png
    output: results/tyndp/NT/cba/all_scenarios.txt
    jobid: 1
    reason: Missing output files: results/tyndp/NT/cba/all_scenarios.txt; Input files updated by another job: results/tyndp/NT/cba/plots_2030, results/tyndp/NT/cba/validation_2030/project_t16_2030.png, results/tyndp/NT/cba/validation_2030/project_t4_2030.png
    wildcards: run=NT
    resources: mem_mb=40000, mem_mib=38147, disk_mb=8000, disk_mib=7630, tmpdir=/scratch/local, runtime=60, partition=big
Touching output file results/tyndp/NT/cba/all_scenarios.txt.
[Fri Jun 19 17:24:43 2026]
Finished jobid: 1 (Rule: collect_cba_scenario)
10 of 11 steps (91%) done
Select jobs to execute...
Job rate limit reached, waiting for free slots.
Execute 1 jobs...

[Fri Jun 19 17:24:53 2026]
localrule cba:
    input: results/tyndp/NT/cba/all_scenarios.txt
    jobid: 0
    reason: Input files updated by another job: results/tyndp/NT/cba/all_scenarios.txt
    resources: mem_mb=40000, mem_mib=38147, disk_mb=8000, disk_mib=7630, tmpdir=/scratch/local, runtime=60, partition=big
[Fri Jun 19 17:24:53 2026]
Finished jobid: 0 (Rule: cba)
11 of 11 steps (100%) done
Complete log(s): /scratch/htc-panfs/mmeng/open-tyndp/.snakemake/log/2026-06-19T164829.560867.snakemake.log

Expected Behavior

The workflow should crash instead in cases such as these.

For example, here is how it looks when using Gurobi as the rolling horizon solver and the optimization fails:

[Fri Jun 19 15:52:32 2026]
rule solve_cba_network:
    input: resources/tyndp/NT/cba/networks/project_t4_2030.nc
    output: results/tyndp/NT/cba/networks/project_t4_2030.nc
    log: results/tyndp/NT/logs/cba/projects/project_t4_2030_solver.log, results/tyndp/NT/logs/cba/projects/project_t4_2030_memory.log, results/tyndp/NT/logs/cba/projects/project_t4_2030_python.log
    jobid: 125
    reason: Missing output files: results/tyndp/NT/cba/networks/project_t4_2030.nc; Updated input files: resources/tyndp/NT/cba/networks/project_t4_2030.nc
    wildcards: run=NT, cba_project=t4, planning_horizons=2030
    resources: mem_mb=40000, mem_mib=38147, disk_mb=8000, disk_mib=7630, tmpdir=<TBD>, runtime=60, partition=big
Submitted job 125 with external jobid 'Submitted batch job 1251534'.
Select jobs to execute...
Execute 1 jobs...

[Fri Jun 19 15:52:42 2026]
rule solve_cba_reference_network:
    input: resources/tyndp/NT/cba/networks/rl_2030.nc
    output: results/tyndp/NT/cba/networks/reference_2030.nc
    log: results/tyndp/NT/logs/cba/reference/reference_2030_solver.log, results/tyndp/NT/logs/cba/reference/reference_2030_memory.log, results/tyndp/NT/logs/cba/reference/reference_2030_python.log
    jobid: 10
    reason: Missing output files: results/tyndp/NT/cba/networks/reference_2030.nc; Updated input files: resources/tyndp/NT/cba/networks/rl_2030.nc
    wildcards: run=NT, planning_horizons=2030
    resources: mem_mb=40000, mem_mib=38147, disk_mb=8000, disk_mib=7630, tmpdir=<TBD>, runtime=60, partition=big
Submitted job 10 with external jobid 'Submitted batch job 1251543'.
Select jobs to execute...
Execute 1 jobs...

[Fri Jun 19 15:52:52 2026]
rule solve_cba_network:
    input: resources/tyndp/NT/cba/networks/project_t16_2030.nc
    output: results/tyndp/NT/cba/networks/project_t16_2030.nc
    log: results/tyndp/NT/logs/cba/projects/project_t16_2030_solver.log, results/tyndp/NT/logs/cba/projects/project_t16_2030_memory.log, results/tyndp/NT/logs/cba/projects/project_t16_2030_python.log
    jobid: 130
    reason: Missing output files: results/tyndp/NT/cba/networks/project_t16_2030.nc
    wildcards: run=NT, cba_project=t16, planning_horizons=2030
    resources: mem_mb=40000, mem_mib=38147, disk_mb=8000, disk_mib=7630, tmpdir=<TBD>, runtime=60, partition=big
Submitted job 130 with external jobid 'Submitted batch job 1251550'.
[Fri Jun 19 16:18:03 2026]
Error in rule solve_cba_network:
    message: For further error details see the cluster/cloud log and the log files of the involved rule(s).
    jobid: 125
    input: resources/tyndp/NT/cba/networks/project_t4_2030.nc
    output: results/tyndp/NT/cba/networks/project_t4_2030.nc
    log: results/tyndp/NT/logs/cba/projects/project_t4_2030_solver.log, results/tyndp/NT/logs/cba/projects/project_t4_2030_memory.log, results/tyndp/NT/logs/cba/projects/project_t4_2030_python.log (check log file(s) for error details)
    external_jobid: Submitted batch job 1251534
[Fri Jun 19 16:20:44 2026]
Error in rule solve_cba_reference_network:
    message: For further error details see the cluster/cloud log and the log files of the involved rule(s).
    jobid: 10
    input: resources/tyndp/NT/cba/networks/rl_2030.nc
    output: results/tyndp/NT/cba/networks/reference_2030.nc
    log: results/tyndp/NT/logs/cba/reference/reference_2030_solver.log, results/tyndp/NT/logs/cba/reference/reference_2030_memory.log, results/tyndp/NT/logs/cba/reference/reference_2030_python.log (check log file(s) for error details)
    external_jobid: Submitted batch job 1251543

Steps to Reproduce

  1. Save this as config/config.zib.yaml:
run:
  name: "NT"

clustering:
  temporal:
    resolution_sector: 1H

solving:
  options:
    assign_all_duals: true
    include_objective_constant: false
  solver:
    name: gurobi
    options: gurobi-default
  partition: big
  mem_mb: 40000
  runtime: 1h

cba:
  planning_horizons:
  - 2030

  projects: [t4, t16]

  msv_extraction:
    solving:
      options:
        include_objective_constant: false
      solver:
        name: gurobi
        options: gurobi-default
      solver_options:
        gurobi-default:
          BarConvTol: 1.0e-06
      partition: big
      mem_mb: 40000
      runtime: 1h

  # Rolling horizon solving settings
  solving:
    options:
      include_objective_constant: false
    partition: big
    mem_mb: 40000
    runtime: 1h

    solver:
      name: highs
      options: highs-simplex

    solver_options:
      highs-simplex:
        primal_feasibility_tolerance: 1.0e-06
        dual_feasibility_tolerance: 1.0e-06
  1. If on ZIB, run: snakemake --profile profiles/slurm -call cba --configfile config/config.tyndp.yaml config/config.zib.yaml.

Environment Information

No response

Metadata

Metadata

Assignees

Labels

CBACost Benefit Analysis

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions