Step 1: Identify Which Subjects Failed¶
Run Post-Run Verification first. Use check-outputs to see which subjects are missing expected output files, and the job database for exit codes and error messages. Once you know which subjects and tasks need attention, come back here to diagnose why.
Step 2: Read the SLURM Logs¶
SLURM output and error files are in {work_dir}/log/{task_name}/:
{work_dir}/log/{task_name}/{task_name}_{job_id}.out
{work_dir}/log/{task_name}/{task_name}_{job_id}.errThe detailed per-subject execution log (stdout + stderr combined) is written by the wrapper:
# Array jobs
{work_dir}/log/{task_name}/sub-{subject}/{task_name}_{job_id}_{array_task_id}_{timestamp}.log
# Non-array jobs
{work_dir}/log/{task_name}/{task_name}_{job_id}_{timestamp}.logStep 3: Inspect the Wrapper Script¶
The generated wrapper script shows exactly what ran on the compute node:
cat /data/work/my_study/log/wrapper/afni_cards_preprocessing_*.shVerify:
Module load commands look correct
Environment variables (
$TEMPLATE_DIR,$CONTAINER_DIR, etc.) are setScript path exists
Step 4: Test the Module Environment¶
SSH to a compute node (or use srun) and manually load the modules:
srun --pty bash
ml AFNI/24.3.06-foss-2023a
afni_proc.py --help # should print help if loaded correctlyStep 5: Check Script Line Endings¶
Windows line endings cause $'\r': command not found errors:
file src/neuromaestro/pipeline/scripts/branch/afni_cards_preprocessing.sh
# Should say "POSIX shell script" or "Bourne-Again shell script", NOT "CRLF"
# Fix if needed:
dos2unix src/neuromaestro/pipeline/scripts/branch/*.shDatabase Shows Incomplete Records?¶
If the database is missing jobs (e.g., after a cluster crash), merge the raw JSONL logs manually:
neuromaestro merge-logs /data/work/my_studyJSONL event logs in {work_dir}/database/json/ accumulate independently of the SQLite database. Merging re-processes any unarchived files and fills in gaps.
If the JSONL files were already archived by a previous merge and the database is still incomplete (e.g., after restoring from backup), use force-rebuild to create a fresh database from all logs including archived ones:
neuromaestro force-rebuild /data/work/my_study
# → writes pipeline_jobs_rebuild_{timestamp}.db next to the originalQuick Diagnosis Checklist¶
Is the config file named
{project}_config.yamland in the right directory?Does
module availshow the modules in your config?Are all paths in
envir_dirabsolute and correct on the HPC?Does the container
.siffile exist incontainer_dir?Does the
license.txtexist infreesurfer_dir?Are shell scripts using Unix line endings?
Does the Python venv contain
typer,pandas?
Error Reference¶
Setup & Configuration¶
“No subjects found”
Check that
prefixin your project config (prefix: "sub-") matches your directory namingVerify
--inputpoints to the correct directoryRun
neuromaestro detect-subjects /data/BIDSto preview what the pipeline sees
“Project configuration not found”
The config file must be named exactly
{project}_config.yamlIt must be in
config/project_config/Check:
ls config/project_config/
“Task not found” / task name mismatch
Task names are case-sensitive —
cards_preprocess≠Cards_PreprocessThe name must match exactly between
config.yamland your project configtaskssectionRun
neuromaestro list-tasksto see all registered task names
GUI won’t start
Check if port 8050 is already in use:
lsof -i :8050Try a different port:
neuromaestro-gui --port 8051Verify the package is installed:
pip show neuromaestro
SLURM & Job Submission¶
module: command not found in job logs
The module system is not initialized in the batch environment
Add to the top of
global_pythonin your project config:global_python: - source /etc/profile.d/modules.sh - ml Python/3.11.3-GCCcore-12.3.0 - . /home/$USER/venv/bin/activate
SLURM Job ID: N/A in database
Job was not submitted properly
Check:
which sbatch(must be available)Check account:
sacctmgr show user $USER
Jobs are queued but never start
Check resource limits:
sacctmgr show assoc user=$USERReduce concurrent array jobs: lower
array_limiton the task’s resource profile inhpc_config.yaml
Container Mounting (Apptainer / Singularity)¶
FATAL: container creation failed: ... squashfuse_ll failed to mount ... in 10s
Apptainer mounts a .sif image with squashfuse (a userspace FUSE mount) and gives up if the mount is not ready within a hard 10 second limit. The image lives on the shared network filesystem (container_dir, e.g. /work). When many jobs mount the same large image at the same time (a job array releasing a batch at once), they all read the image over the network and contend for storage bandwidth, so individual mounts exceed 10s and fail.
This is probabilistic, not deterministic. It is far more likely with:
Large images (fMRIPrep, QSIPrep, QSIRecon, MRIQC are 10 to 20 GB)
High concurrency (many array tasks starting in the same window)
Peak cluster hours (Monday morning, weekday daytime) and shared (non-dedicated) nodes
The processing scripts avoid this by staging the image to node-local disk before running:
The image is copied once to
/tmp/${USER}_sif/on the compute node, and the container runs from that local copy. A local squashfuse mount completes in well under a second, so the 10s timeout never triggers.A per-node
flockguarantees only one job on a node copies the image; other jobs wait and then reuse the same copy, so a burst of same-node jobs does not each copy in parallel.If staging fails (see disk-full below), the script prints a warning and falls back to the network image, so the job still runs.
APPTAINER_TMPDIR/SINGULARITY_TMPDIRare also pointed at node-local disk for session scratch.
This is the block near the top of each processing script (before singularity run). Copy it into any new container script, then run singularity run ... ${local_container} ... instead of ${CONTAINER_DIR}/${CONTAINER}:
# Point Apptainer session/cache to node-local disk to avoid squashfuse mount timeout
apptainer_tmp="${SLURM_TMPDIR:-${TMPDIR:-/tmp}}/apptainer_${SLURM_JOB_ID:-$$}"
mkdir -p "${apptainer_tmp}"
export APPTAINER_TMPDIR="${apptainer_tmp}"
export APPTAINER_CACHEDIR="${apptainer_tmp}"
export SINGULARITY_TMPDIR="${apptainer_tmp}"
export SINGULARITY_CACHEDIR="${apptainer_tmp}"
# Stage container image to node-local disk to avoid squashfuse mount timeout.
# Per-node lock: only one job copies, others wait then reuse. Fall back to the
# network image if staging fails (e.g. local disk full).
src_container="${CONTAINER_DIR}/${CONTAINER}"
node_cache="/tmp/${USER}_sif"
staged="${node_cache}/${CONTAINER}"
local_container="${src_container}"
mkdir -p "${node_cache}" 2>/dev/null
(
flock 9
if [ ! -s "${staged}" ] || [ "$(stat -c%s "${staged}" 2>/dev/null)" != "$(stat -c%s "${src_container}")" ]; then
tmp_copy="${staged}.tmp.$$"
cp "${src_container}" "${tmp_copy}" 2>/dev/null && mv -f "${tmp_copy}" "${staged}" || rm -f "${tmp_copy}"
fi
) 9>"${node_cache}/${CONTAINER}.lock"
if [ -s "${staged}" ] && [ "$(stat -c%s "${staged}" 2>/dev/null)" = "$(stat -c%s "${src_container}")" ]; then
local_container="${staged}"
else
echo "WARNING: staging to ${node_cache} failed (disk full?), using network image"
fiIf mount timeouts still appear (staging fell back to the network image), also:
Lower concurrency via
array_limiton the task’s resource profile inhpc_config.yamlSubmit off-peak, or use dedicated nodes when available
cp: ... No space left on device when staging the image
Node-local /tmp filled up. On shared nodes /tmp is shared with other users’ jobs, so it can be nearly full before your copy starts. The scripts handle this gracefully (fall back to the network image), so the job does not hard-fail, but that job loses the staging benefit.
Inspect a compute node:
srun --pty bash -c 'df -h -T /tmp; du -sh /tmp/${USER}_sif'Clear your own leftovers on a node:
srun -w <node> bash -c 'rm -rf /tmp/${USER}_sif'Most clusters reap
/tmpautomatically (epilog or tmpwatch); only your own files (/tmp/${USER}_sif,/tmp/apptainer_*) are yours to remove
Python Environment¶
ModuleNotFoundError: No module named 'typer'
The Python environment on the compute node is missing required packages
Ensure your venv/conda env includes:
typer,pandas,sqlite3Test on a compute node:
srun --pty bash -c "source /path/to/venv/bin/activate && python -c 'import typer'"
Resume & Output Checks¶
--resume does not skip any subjects
Check that
{project}_checks.yamlexists inconfig/results_check/Tasks with no entry in the checks file are always submitted in full (warning is printed)
check-outputs reports unexpected failures
Open the CSV at
{work_dir}/check_results_{timestamp}.csv— thepatternandactualcolumns show exactly what was globbed and how many files were foundVerify
output_pathresolves correctly for your subjects by checking the path manually on the HPCCheck
expected_countandtolerancematch your actual data