Common issues¶
Audience: all users. Scope: the issues that hit most often during day-to-day operation, with the symptom, the cause, and the fix.
This page is a triage starting point, not a complete catalogue. For deeper investigation see Status-bar symptoms (for live-run distress) and Reading event logs (for post-mortem). For a corrupted bundle see Crash recovery.
Each section follows the same shape: Symptom → Cause → Fix.
Sartorius balance doesn't open on the first try¶
Symptom. Capa starts up. The Sartorius card shows "opening…" and stays there for a few seconds. Eventually it succeeds, or it gives up with SartoriusTransportError: cold-open frame underrun.
Cause. The Sartorius YDP/SBI protocol has a well-known cold-open race: the first read from the serial port after the device powers on can return a zero-byte frame before the balance's controller has finished its own boot sequence. The library handles this with a bounded retry; the visible "opening…" period is that retry loop. See the _build_balance notes in devices/sartorius.py.
Fix. Wait. The retry is bounded by the configured timeout_s (default ~3 s) and almost always succeeds within that window. If it doesn't:
- Confirm the balance is actually powered on and the cable is seated.
- Confirm no other process holds the COM port (Sartorius display software, a previous capa instance that wasn't fully closed).
- Confirm the serial settings in
hardware.tomlmatch the balance's menu (baud, parity, stop bits, protocol kind).
If the open succeeds on the second capa launch but not the first, the cold-open race is the cause and the existing retry should have caught it — file a bug with the bundle's run.log so the retry schedule can be tuned. See Reporting bugs.
NI-DAQ chassis not found¶
Symptom. Pool open fails with NIDAQError: device "cDAQ1" not found or similar, or the NI-DAQ worker stays IDLE with no channels discovered.
Cause. One of three things, in rough order of frequency:
- NI-DAQmx runtime not installed. Capa imports
nidaqmx; the underlying driver is a separate NI install (NI-DAQmx Runtime ≥ 2024 Q3). - Chassis powered off, USB cable unseated, or chassis claimed by another process. Confirm with NI MAX (NI Measurement & Automation Explorer) — if the chassis doesn't appear there, capa can't see it either.
- Chassis name mismatch. The
channelsentries inhardware.tomlencode the chassis name (e.g.cDAQ1Mod1/ai0). If NI MAX renamed the chassis (e.g.cDAQ2after a USB replug), update the config.
Fix.
# Verify the driver is loaded
python -c "import nidaqmx.system; print(nidaqmx.system.System.local().devices.device_names)"
If that prints (), the driver isn't seeing any hardware — start at NI MAX. If it prints chassis names that don't match your hardware.toml, update the config.
FLIR Atlas DLL not on PATH¶
Symptom. Capa fails to import the FLIR IR adapter at startup: ImportError: DLL load failed while importing _flir_atlas or OSError: cannot load library 'AtlasIPxxx.dll'. The IR worker never comes up.
Cause. The FLIR Atlas SDK installs its DLLs into a directory that isn't on the Python process's PATH by default. On Windows this typically means C:\Program Files\FLIR Systems\sdks\file\Atlas\bin (or similar) is missing from the user environment.
Fix.
- Confirm the SDK is actually installed:
Get-ChildItem "C:\Program Files\FLIR Systems"(or your install path). - Add the Atlas
bindirectory to the userPATH. Re-open the terminal / re-launch capa so the change takes effect. - Verify the import:
This is a per-machine setup issue, not a runtime issue. Once PATH is right it stays right. See cameras-flir.md for the broader FLIR install story.
Camera encoder choice causing saturation¶
Symptom. A run starts fine, then within 30–60 s the sat pill turns yellow then red on the status bar. Loop lag (loop) stays low. The Acquisition Diagnostics dock shows every worker's Age climbing in lockstep — not just the camera. events.sqlite shows a saturation_deadline event whose metadata's resource_id is webcam:0 or flir_ir:0.
Cause. The configured video codec is libx264 (the default), which encodes on a single CPU thread in the writer process. At high resolution × high fps × dual-camera, encode can't keep up with capture; the writer's inbox fills; the conductor's drain blocks on await writer.record_frame(...); every bridge backs up. This is the canonical mechanism behind a saturation trip with loop low.
Fix. Swap the codec in hardware.toml for the offending camera:
[devices.visible_cam0.params]
codec = "h264_qsv" # Intel iGPU (zero-CPU encode on supported chipsets)
# codec = "h264_nvenc" # NVIDIA GPU encode
# codec = "mjpeg" # no inter-frame compression; much larger files; near-zero CPU
Defaults live in devices/camera/webcam/constants.py. The hardware-accelerated codecs require either an Intel CPU with Quick Sync or an NVIDIA GPU; mjpeg works everywhere but produces bundles 5–10× larger.
Reload the config and try a short test run. The sat pill should stay green; the diagnostics dock should show every camera's Age stable below 1 s. See also cameras-webcam.md.
Disk filling up mid-run¶
Symptom. The disk pill turns yellow (< 15% free) then red (< 5% free). Shortly after, sat follows.
Cause. Camera bitrate dominates bundle size. A 30 fps dual-camera run at libx264 is typically 50–100 MB/min; at mjpeg it can be 500 MB/min or more. NI-DAQ at high sample rates also contributes (5 Hz × 64 channels × 8 bytes × 60 s ≈ 150 KB/min — negligible by comparison).
Fix, by urgency.
diskyellow, run still going: finish the run if you can. Do not start a new run on this volume.diskred, run still going: stop the run cleanly if the rig allows it. The writer will eventually stall onENOSPC, which trips saturation and seals ascrashed_but_sealed.- After: free space, or launch with
--runs-root/CAPA_RUNS_ROOTpointing at a larger volume. If you also use profile disk-space preflight, keepstorage.bundle_rootaligned with the actual runs root.
Pre-flight estimate. Roughly bundle_size ≈ Σ(producer_rate × bytes_per_sample × duration_s) + video_bitrate × duration_s. For a one-hour capa_real_full run, plan on 6–10 GB at default settings, or 30–60 GB with mjpeg.
Procedure plugin entry-point not discovered¶
Symptom. A procedure plugin you installed via uv pip install capa-myplugin doesn't show up in capa plugins list or in the GUI's procedure picker.
Cause. Three possibilities, ranked:
- Lockfile is stale. In production mode, capa enforces a plugin lockfile to make runs reproducible — see Plugin lockfile. A procedure plugin installed but not present in the lockfile is rejected.
- Entry-point typo. The plugin's
pyproject.tomlmust declare the entry-point under thecapa.proceduresgroup. Check with: - Wrong Python environment. Capa is running under a different
uv-managed venv than the one where you installed the plugin.
Fix.
# Confirm capa sees the plugin's entry-point
capa plugins list
# If listed but not loaded → lockfile gate
capa plugins trust <plugin-id> --reason "approved for this rig"
# If not listed at all → entry-point or env problem
uv pip show capa-myplugin # confirm it's in the active environment
See Plugin system for the full discovery and gating mechanism.
Device adapter descriptors are a separate surface: they use capa.adapters / capa.cameras, show up through capa hardware discover and the Setup registry, and are not listed by capa plugins list.
Not finding what you need?¶
This page covers the most common issues, not all of them. For deeper triage:
- Live run looks wrong → Status-bar symptoms.
- Past run looks wrong → Reading event logs.
- Bundle won't open / appears partial → Crash recovery.
- Reporting it as a bug → Reporting bugs.