Problem
When a study file is submitted with targets: null (simulation-only, no target evaluation), the runner completes successfully but does not persist model outputs to blob storage. The outputs exist in Dask worker memory during execution but are never written to parquet.
The runner code at src/modelops/runners/job_runner.py:339 has a literal TODO:
elif not target_entrypoints:
logger.warning("Skipping view generation: write_job_view requires aggregated results with targets")
logger.info("TODO: Implement write_sim_results_view() for jobs without targets")
Impact
This blocks the klebsim incidence sweep analysis, which uses a single-site model with no targets — the baseline Sobol sweep runs 1000 simulations successfully, but the kp_counts.parquet output is not downloadable because it was never written to storage.
Any workflow that runs simulations without target evaluation is affected.
Fix
The default_results list contains all SimReturn objects with their .outputs dictionaries. These need to be concatenated by output name and written to blob storage at jobs/{job_id}/model_outputs/{output_name}.parquet, mirroring the path structure used by jobs with targets.
A fix is implemented on branch fix/runner-no-target-outputs (PR forthcoming).
Workaround
Register a dummy target that always succeeds, forcing the runner through the existing write path. Not ideal since it wastes compute on unnecessary target evaluation.
Problem
When a study file is submitted with
targets: null(simulation-only, no target evaluation), the runner completes successfully but does not persist model outputs to blob storage. The outputs exist in Dask worker memory during execution but are never written to parquet.The runner code at
src/modelops/runners/job_runner.py:339has a literal TODO:Impact
This blocks the klebsim incidence sweep analysis, which uses a single-site model with no targets — the baseline Sobol sweep runs 1000 simulations successfully, but the
kp_counts.parquetoutput is not downloadable because it was never written to storage.Any workflow that runs simulations without target evaluation is affected.
Fix
The
default_resultslist contains allSimReturnobjects with their.outputsdictionaries. These need to be concatenated by output name and written to blob storage atjobs/{job_id}/model_outputs/{output_name}.parquet, mirroring the path structure used by jobs with targets.A fix is implemented on branch
fix/runner-no-target-outputs(PR forthcoming).Workaround
Register a dummy target that always succeeds, forcing the runner through the existing write path. Not ideal since it wastes compute on unnecessary target evaluation.