# Diagnose and fix OpenMC cross-section data setup failures

Fix OpenMC nuclear-data errors by classifying the exact error first: missing cross_sections.xml pointer (OPENMC_CROSS_SECTIONS / materials.cross_sections) vs missing S(alpha,beta) thermal-scattering table vs nuclide absent from the library; generate matching libraries with openmc_data_downloader.

Exact reference: {"kind":"skill_version","skill_id":"skl_ucZF_5CpZNd_h1B7TIit4g","version_id":"skv_cXoHWFso56Cvdz2Fl3tdSQ"}

Applicability: [{"constraint":">=0.13 (error text verified in 0.13 docs; decay-only nuclide allowance needs 0.14+)","technology":"OpenMC","version_scheme":"semver"},{"constraint":"any recent release (CLI flags -l/-m/-e/-i/-s/-p and Python download_cross_section_data verified)","technology":"openmc_data_downloader","version_scheme":"unknown"}]

# Diagnose and fix OpenMC cross-section data setup failures

Use this when OpenMC refuses to run (or a material call raises) because it
cannot find nuclear data. Nearly every data error is one of three distinct
problems with different fixes, so read the exact error first and classify it
before downloading anything.

## 1. Read the exact error and classify

OpenMC prints three different messages for three different problems:

- **"ERROR: No cross_sections.xml file was specified in settings.xml or in the
  OPENMC_CROSS_SECTIONS environment variable."** — OpenMC cannot find the
  `cross_sections.xml` index at all. (In current releases the `&lt;cross_sections&gt;`
  element lives in `materials.xml`, not `settings.xml`; the Python API
  equivalent is `RuntimeError: No cross_sections.xml file was specified in
  materials.xml or in the OPENMC_CROSS_SECTIONS environment variable`.) Fix:
  point OpenMC at an existing file (step 2), not download new data.
- **"ERROR: Could not find S(a,b) table X in cross_sections.xml file!"** — the
  index was found, but the thermal-scattering table your material requests is
  not in it. Fix: the S(alpha,beta) name or the library (step 4), not the
  pointer.
- **`ValueError` from `add_element()` / `add_nuclide()`**, e.g. "No data is
  available for any of natural isotopes of the element" — the isotope you
  asked for exists in your model but not in the data library the index points
  to. Fix: the library (step 3), not the pointer.

Do not treat all three as "I need more data" — the first two are usually
configuration, not missing physics.

## 2. Fix the "no cross_sections.xml" pointer

OpenMC resolves the index in this order; set whichever fits your workflow:

1. The `cross_sections` attribute in the Python API, exported as the
   `&lt;cross_sections&gt;` element in `materials.xml` (older releases:
   `settings.xml`):

   ```python
   materials = openmc.Materials([fuel, water])
   materials.cross_sections = '/path/to/nuclear_data/cross_sections.xml'
   materials.export_to_xml()
   ```

2. The `OPENMC_CROSS_SECTIONS` environment variable (recommended for the
   shell profile so every run inherits it):

   ```bash
   export OPENMC_CROSS_SECTIONS=/path/to/nuclear_data/cross_sections.xml
   ```

After setting either, sanity-check that the path exists and that the file
actually references HDF5 data files on disk:

```bash
test -f "$OPENMC_CROSS_SECTIONS" && echo "index found"
head -5 "$OPENMC_CROSS_SECTIONS"
```

A `cross_sections.xml` that lists `.h5` files you never downloaded (or that
live on someone else's machine) produces the same missing-data symptoms as a
bad pointer — the error message won't tell you which, so check the file
contents.

## 3. Get a library that covers your nuclides

If the pointer is fine but nuclides are missing, generate a library whose
contents are derived from your actual materials instead of downloading a
generic bundle and hoping:

```bash
pip install openmc_data_downloader
openmc_data_downloader -l ENDFB-7.1-NNDC -m materials.xml
```

The `-m materials.xml` form downloads exactly the isotopes present in your
materials file and writes a matching `cross_sections.xml`. For common cases:

```bash
openmc_data_downloader -l ENDFB-7.1-NNDC -e Li Si Na -i Fe56 U235   # elements + isotopes
openmc_data_downloader -l FENDL-3.1d -i Li6                       # single isotope
openmc_data_downloader -l TENDL-2019 -i stable                    # all stable isotopes
```

Or do it inside Python — `just_in_time_library_generator()` sets
`OPENMC_CROSS_SECTIONS` for you by default:

```python
import openmc_data_downloader as odd

odd.download_cross_section_data(
    mats,
    libraries=['ENDFB-7.1-NNDC'],
    set_OPENMC_CROSS_SECTIONS=True,
    particles=['neutron'],
)
```

Since OpenMC 0.14, depletion runs may include decay-only nuclides with no
neutron data, so a "no data" complaint about a pure decay nuclide is
expected and harmless in depletion — only fissionable/absorbing nuclides in
the transport solve need tables.

## 4. Fix S(alpha,beta) thermal-scattering mismatches

This error means the *name* of the table in your material does not match any
`&lt;library ... type="neutron"&gt;` entry with `materials="..."` S(a,b) alias in
your `cross_sections.xml`. Two frequent causes:

- **Legacy table names.** Old example inputs and forum posts use ACE-era
  aliases like `lwtr.15t` (water at 550 K) or `lwtr.10t` (293 K). Modern
  OpenMC data libraries use names such as `c_H_in_H2O`, `c_Graphite`,
  `c_H_in_ZrH`, `c_Be_in_BeO`. Set the current name explicitly:

  ```python
  water.add_s_alpha_beta('c_H_in_H2O')
  graphite.add_s_alpha_beta('c_Graphite')
  ```

- **The table was never downloaded.** The library index you downloaded may
  not include S(a,b) tables. Download them by name with the downloader:

  ```bash
  openmc_data_downloader -l ENDFB-7.1-NNDC -e Be O -s c_Be_in_BeO
  ```

  or in Python, declare the table on the material first so `-m
  materials.xml` picks it up:

  ```python
  my_mat = openmc.Material()
  my_mat.add_element('Be', 0.5)
  my_mat.add_element('O', 0.5)
  my_mat.add_s_alpha_beta('Be_in_BeO')
  ```

Note the naming split: the Python API takes names like `Be_in_BeO`, the
`cross_sections.xml` alias is typically `c_Be_in_BeO`; the downloader handles
both forms. If a forum post or old input gives you an alias ending in
`.Nt` / a number like `71c`, that alias belongs to an old data generation
and you should re-derive the current name from your actual library file,
not copy the alias.

## 5. Photon data is a separate download

Neutron-only libraries do not contain photon interaction data. If you enable
photon transport (`settings.photon_transport = True`), request both particle
types when building the library or the run will fail on missing photon
tables:

```bash
openmc_data_downloader -l ENDFB-7.1-NNDC -e Li -p neutron photon
```

```python
odd.download_cross_section_data(
    mats,
    libraries=['ENDFB-7.1-NNDC'],
    set_OPENMC_CROSS_SECTIONS=True,
    particles=['neutron', 'photon'],
)
```

## 6. Checklist for the failing command

1. Capture the exact error text and classify it (pointer vs S(a,b) name vs
   missing nuclide) — the fix differs for each.
2. Pointer error: set `materials.cross_sections` or `OPENMC_CROSS_SECTIONS`
   and verify the file exists with `test -f`.
3. Missing nuclide: regenerate the library from your materials with
   `openmc_data_downloader -l [library] -m materials.xml`.
4. S(a,b) error: check the table alias against your `cross_sections.xml`,
   update legacy names (e.g. `lwtr.15t`) to current ones (e.g.
   `c_H_in_H2O`), and download the table with `-s` if absent.
5. Photon transport: rebuild the library with `particles=['neutron',
   'photon']`.
6. Never copy a `cross_sections.xml` path from another machine's forum post
   — the HDF5 paths inside it are local to whoever generated it.


## Supporting basis and limitations

Built from the OpenMC user's guide troubleshooting section (No cross_sections.xml error), the OpenMC Discourse forum threads on the cross_sections.xml RuntimeError and the missing S(a,b) table error, the openmc_data_downloader documentation (CLI and just_in_time_library_generator API), and the openmc.Settings/openmc.statepoint API docs for entropy and k-effective attributes. The draft was written from these sources' error strings, API names, and documented behavior.

## Change and rationale

New skill: diagnose and fix OpenMC cross-section data setup failures.

Cross-section configuration is the single most repeated OpenMC support question (no cross_sections.xml, missing S(a,b) tables, nuclides absent from the library), and users habitually treat all three as 'download more data'. This skill adds a decision procedure that classifies the failure from the exact error message before prescribing the fix.
