# Troubleshooting & FAQ

A symptom → cause → fix reference for the problems newcomers hit most. Grouped by phase: **build/install**,
**import**, **runtime**, and **parallel**.

## Build & install

**`import qc` fails: `undefined symbol: omp_get_num_procs`** (MKL build)
: The MKL threading layer is not pinned. Set **`MKL_THREADING_LAYER=GNU`** (and `MKL_INTERFACE_LAYER=LP64`).
  `make setup` writes these into `.vscode/my.env` and `env.sh`; make sure your shell/kernel loads them.

**`import qc` fails: `symbol not found … __gfortran_concat_string`** (macOS, `openblas-bundled`)
: The statically-linked OpenBLAS/LAPACK needs `libgfortran` at load. Link it as a dylib via `RUSTFLAGS`
  (`-L $(brew --prefix gcc)/lib/gcc/current -l dylib=gfortran`), as in the
  [installation chapter](../00-intro/installation-and-make-setup.md).

**Build fails looking for `libxc.pc`**
: The system libxc is not found. Use the **bundled** source: `--features xc-bundled` (instead of
  `xc-system`).

**Plain `cargo build -p qc-py` fails with Python C-API symbols**
: Build the extension with **`maturin develop` / `maturin build`**, not plain `cargo build` — maturin supplies
  the extension-module linker configuration.

## Import & environment

**`ModuleNotFoundError: No module named 'qc'`** (in a notebook or script)
: The interpreter/kernel is **not the uv venv that has qc-rs installed**. In VSCode pick the right kernel
  (the one under your `uv` project); in a shell activate that venv. Verify with `import sys;
  print(sys.executable)` — it must be your `…/.venv/bin/python`.

**`import qc` breaks right after `uv add …`**
: **`uv add` prunes the editable `qc_rs` extension** from the venv. Rebuild it: `make install` (or
  `maturin develop`). This is expected after adding any dependency.

**`qc.GPU_ENABLED` / `qc.XC_ENABLED` / `qc.PCM_ENABLED` is `False` unexpectedly**
: That feature was not compiled in. Rebuild with the feature (`--features …,cuda` / `xc-bundled` / `pcm`). A
  default build is CUDA-free (`GPU_ENABLED == False`).

## Runtime

**`ValueError: eri="4c-cuda" requires … the cuda feature and a CUDA GPU`**
: You requested a GPU strategy on a non-`cuda` build (or with no visible GPU). Rebuild with `cuda`, or use a
  CPU `eri=` ([GPU chapter](../30-hpc/gpu-cuda.md)).

**`ValueError: unknown iop key "…"`**
: A misspelled/nonexistent IOP key. List valid keys with `qc.iop.list()` and inspect one with
  `qc.iop.describe(key)` ([IOP reference](iop.md)).

**RI-MP2 errors or returns a wrong number**
: RI-MP2 needs a **correlation-fitting auxiliary basis** — set `ric=` on `qc.chk.new(...)` (e.g.
  `ric="cc-pvdz-ri/mp2fit"`). There is no non-RI MP2 path ([post-SCF chapter](../20-guide/post-scf.md)).

**Every bond is ~1.9× too long / SCF will not converge on a pasted geometry**
: You gave **atomic-unit coordinates without `unit="bohr"`**. The default is ångström. Check with
  `mychk.coordinates()` (always bohr) and set `unit=` correctly.

**`ImportError: qc.view 3D rendering needs py3Dmol`**
: Install the viewer dependency: `uv add py3dmol --project "$UV_PROJECT"` (then rebuild qc-rs, since `uv add`
  prunes it). The 2-D `plot_*` calls use matplotlib and are unaffected.

**SCF `converged == False`**
: Read the transcript (`run(log="stdout")`). Energy still dropping → raise `max_cycle` or use a second-order
  `algorithm="qc"/"trah"`; oscillating → add `damping`/`level_shift`, or `smearing` for a small gap
  ([SCF chapter](../20-guide/scf.md)).

**Out-of-memory with `eri="4c-incore"`**
: The full integral set does not fit in RAM. Use `4c-auto` (auto-fallback), `4c-direct` (recompute), or the
  RI family ([ERI strategies](../30-hpc/eri-jk-strategies.md)).

**An open shell (e.g. a symmetric cluster cation) will not converge as ROHF**
: A near-degenerate/delocalized-hole state is multireference and cannot be a single-determinant ROHF. Use
  **UHF/UKS**, often with `guess(..., spin_break="mix")` ([SCF chapter](../20-guide/scf.md)).

## Parallel (MPI / threads)

**More cores (`nthread=`) give no speedup**
: The molecule is small and its bottleneck is the (serial) integral assembly, not the threaded XC/BLAS regions
  (Amdahl). Larger DFT jobs scale ([threads chapter](../30-hpc/threads-and-blas.md)).

**A cluster MPI job hangs at startup with no error**
: The interconnect transport was not selected. Check `cat /sys/class/infiniband/*/ports/*/state` (should be
  `ACTIVE`); select it explicitly, or fall back to shared-memory `--mca pml ob1 --mca btl self,sm`
  ([MPI chapter](../30-hpc/mpi-and-interconnects.md)).

**`PML UCX could not be selected`**
: mpi4py initialized `THREAD_MULTIPLE`, which this UCX cannot use. Put `import mpi4py;
  mpi4py.rc.thread_level = "serialized"` **before** `from mpi4py import MPI`.

**`no auxiliary transport … Destination is unreachable`** (UCX)
: The UCX RC transport needs the `ud` auxiliary. Include `ud_verbs` in `UCX_TLS` (e.g.
  `rc_verbs,ud_verbs,sm,self`).

**`ibv_reg_mr … Cannot allocate memory`** (InfiniBand, in a batch job)
: The `memlock` ulimit is too low. The admin must raise `LimitMEMLOCK` on the compute nodes (batch jobs
  inherit the low cap).

**MPI job is slower cross-node than expected**
: It likely fell back to **TCP/Ethernet** instead of InfiniBand, or is communication-bound. Select the IB
  transport explicitly; forward the env with `-x`; bind ranks with `--map-by numa --bind-to core`.

## Still stuck?

The AI coding assistant in your terminal ([Claude Code / Codex](../00-intro/ai-coding-clis.md)) can read the
error and your build config and usually diagnose it in one step — this is the intended qc-rs workflow. For
bugs, the project uses GitHub Issues.
