Troubleshooting¶
Something went wrong. This page collects solutions to the most common problems researchers run into on Unity. Each entry explains why the problem happens (not just how to fix it) so you can recognize similar issues in the future.
If your problem isn't listed here, see Getting More Help at the bottom of the page.
Jobs¶
My job is stuck in PENDING — how do I find out why?
A pending job simply means Unity hasn't been able to schedule it yet. The scheduler records a reason code for every waiting job. Retrieve it with:
Or just squeue --me for a quick look. Common reason codes and what they mean:
| Reason | Meaning |
|---|---|
Resources | Waiting for enough nodes/CPUs/memory to free up — normal queue wait. |
Priority | Other jobs have higher priority and are ahead of yours in the queue. |
QOSMaxCpuPerUserLimit | You've hit your per-user CPU quota. Wait for a running job to finish. |
ReqNodeNotAvail | You requested a node or feature the cluster can't satisfy (e.g., more memory per node than any node has, or a GPU count that doesn't exist). Double-check your #SBATCH resource requests. |
Maintenance | The cluster is in a scheduled maintenance window; jobs will start when it ends. |
If the reason is ReqNodeNotAvail and you're sure the cluster isn't in maintenance, the most likely cause is an impossible resource combination. For example, requesting 512 GB of memory on a node type that only offers 256 GB. Review the partition limits with sinfo -o "%P %l %m %c" and adjust your request accordingly.
My job was killed with state OUT_OF_MEMORY (OOM) — what do I do?
An OOM kill means your job used more memory than you asked for. Unity's scheduler strictly enforces memory limits: when a job exceeds its allocation, the kernel terminates it immediately, often without a helpful error message in your output.
Diagnose: inspect the job's actual peak memory usage with sacct:
MaxRSS is the peak resident memory your job used; ReqMem is what you requested. If MaxRSS is at or above ReqMem, that's your problem.
Fix: increase your memory request in your job script:
#SBATCH --mem=32G # total memory for the job
# or, if using multiple CPUs:
#SBATCH --mem-per-cpu=8G # memory per CPU core
Tip: after a successful run, use seff JOBID to see efficiency statistics including actual memory usage. This helps you set a realistic (and not wasteful) memory request for future jobs:
My job finished instantly with a non-zero exit code and produced no output
A near-instant failure with no output almost always means the job script itself couldn't run to completion; the work never started. Check the .err file Slurm wrote (named slurm-JOBID.err by default, or whatever you set with --error=). Common culprits:
-
Missing
module load— if you tested a command interactively and it worked, your interactive shell may have had a module loaded that your batch script doesn't. Batch jobs start with a minimal environment. Always load every required module explicitly in your job script:See Software Modules for details on using modules inside job scripts.
-
Wrong file paths — relative paths are resolved from the working directory at job submission time, which may not be where you expect. Prefer absolute paths (e.g.,
/scratch/username/myproject/input.csv) or set your working directory explicitly with#SBATCH --chdir=. -
Script syntax error — a typo or missing quote in your Bash script causes an immediate exit. Run
bash -n myscript.shlocally to check for syntax errors before submitting.
My job ran but the output file is empty
An empty output file means the script executed but nothing was written where you expected. A few things to check:
-
Output directory doesn't exist. Slurm will not create missing directories. If your script writes to
results/output.txtbut theresults/directory doesn't exist on the compute node's filesystem, the write silently fails. Create the directory before submitting, or addmkdir -p resultsto your script. -
Program writes to stderr, not stdout. Many tools print results to standard error by default. Slurm captures stdout and stderr separately. Redirect stderr into the same file to capture everything:
Or combine Slurm's output and error streams with
#SBATCH --outputand#SBATCH --errorpointing to the same file. -
Working directory mismatch. The output path in your program may be relative to a directory that isn't the current directory when the job runs. Use absolute paths or verify the working directory with
echo $PWDat the top of your script.
My job ran successfully but produced wrong or unexpected results
Unexpected results are almost always an environment or path problem, not a cluster problem. The scheduler ran your script exactly as written, but the script did something unintended. Start by adding these two lines near the top of your job script to capture diagnostic information in the output:
Common causes:
- Wrong input path. Relative paths are resolved from the submission directory, which may differ from where you think. Use absolute paths for all input and output files (e.g.,
/scratch/netid/project/input.csv). - Wrong module version. If you have multiple versions of a tool installed, the wrong one may be loaded.
module listin your job output will tell you exactly what was active. - Output written to the wrong location. A common confusion is writing to
$HOMEwhen you intended scratch, or vice versa. Check both locations. - Race condition in parallel code. Multiple workers writing to the same file without locking will corrupt output. Use separate per-worker output files and merge afterward, or use a thread-safe output mechanism.
Tip
Add set -euo pipefail as the second line of every Bash job script (right after #!/bin/bash). This makes the script exit immediately on any unhandled error, undefined variable, or failed pipe, catching problems early instead of silently producing wrong results.
I submitted too many jobs — how do I cancel them all?
Slurm gives you several scancel options depending on how many jobs you want to remove:
# Cancel every one of your jobs (running and pending)
scancel -u $USER
# Cancel only your PENDING jobs (leave running jobs alone)
scancel -u $USER --state=PENDING
# Cancel a single specific job
scancel JOBID
# Cancel a range of consecutive job IDs (Bash brace expansion)
scancel {10000..10099}
For job arrays, you have finer control:
# Cancel the entire array
scancel ARRAYJOBID
# Cancel a single task within the array
scancel ARRAYJOBID_TASKID
Warning
scancel -u $USER is immediate and irreversible. There is no undo. If you want to pause jobs temporarily instead of deleting them, use scontrol hold JOBID / scontrol release JOBID.
See the job arrays recipe for more on managing large batches of work.
Python¶
ModuleNotFoundError on the cluster, but the package is installed on my laptop
The package isn't missing from the cluster; it's just not in the Python environment your batch job uses. When you install packages interactively (e.g., pip install numpy in a terminal), they go into your active virtual environment. But a batch job starts a fresh shell with no virtual environment activated, so it falls back to the system Python, which doesn't have your packages.
Fix: activate your virtual environment explicitly in your job script, before calling Python:
#!/bin/bash
#SBATCH --job-name=my-python-job
#SBATCH --ntasks=1
#SBATCH --mem=8G
source /path/to/your/.venv/bin/activate
python my_script.py
If you use uv to manage environments (recommended), see the uv recipe for the correct activation pattern and how to structure your environment so it's always accessible from batch jobs.
CUDA error: no kernel image is available for execution on the device
This error means PyTorch (or another CUDA library) was compiled for a different CUDA version than the one the GPU driver supports. A PyTorch build targeting CUDA 11.8, for example, will not run on a node whose driver only exposes CUDA 12.x kernels, or vice versa.
Diagnose: check what CUDA version the GPU supports:
Look for the "CUDA Version" in the top-right corner of the output. This is the maximum CUDA version the driver supports.
Fix: reinstall PyTorch with a CUDA index that matches. For example, if the driver reports CUDA 12.1:
See the PyTorch recipe for the full setup walkthrough, including how to verify the installation before submitting a batch job.
CUDA out of memory — my training job crashes partway through
Your model, activations, or batch data exceed the GPU's available VRAM. Unlike system RAM, GPU memory is not virtual. There's no swap, so the process crashes immediately when it runs out.
Diagnose: see how much VRAM your job is actually using:
Or add nvidia-smi as a command inside your job script to log usage at a point during the run.
Options to reduce memory usage:
- Reduce batch size — the most direct lever. Halving the batch size roughly halves the activation memory.
- Use mixed precision —
torch.cuda.ampruns forward passes in FP16/BF16, cutting memory roughly in half with minimal accuracy loss: - Gradient checkpointing — trades compute for memory by recomputing activations during the backward pass instead of storing them.
- Request a larger GPU — if the cluster has nodes with higher-VRAM GPUs, specify the GPU model with
--gres=gpu:a100:1(or the appropriate type). Checksinfo -o "%P %G"to see what GPU types are available.
My virtual environment works interactively but fails in a batch job
The most common reason is that your batch job script doesn't set up the same environment your interactive shell has. Batch jobs start with a minimal environment, with no modules loaded and no virtual environments activated.
Work through this checklist:
- Load the right Python/uv module first. Even before activating the environment, you need the same Python toolchain: For
module load python/3.11 # or whichever version you used to create the env source /path/to/.venv/bin/activateuv-managed environments, useuv rundirectly instead: - Use absolute paths. Relative paths to the environment break when the working directory differs between submission and execution. Prefer
/scratch/username/project/.venvover.venv. - Check home directory accessibility. In rare cases, NFS issues can make home unavailable on a compute node. If your environment lives in
$HOME, tryls $HOMEinside the job script and check the output. - Use the correct activation method for your tool. For conda, load the module first (
module load conda/latest) thenconda activate myenv. Foruv, useuv rundirectly.
Tip
Add which python && python --version near the top of your job script. The output in your .out file will confirm immediately whether the right interpreter is active.
See the uv recipe and the conda recipe for canonical batch job templates.
My code works on one GPU but crashes when I use multiple GPUs
Single-GPU code doesn't automatically scale. Multi-GPU training requires explicit distributed training setup. If you just request multiple GPUs without initializing a process group, only the first GPU will be used (or the job will crash with a confusing error).
The most common fix: follow the multi-GPU recipe to initialize PyTorch Distributed Data Parallel (DDP) or use HuggingFace Accelerate, which handles the boilerplate for you.
Other things to check:
- NCCL errors (e.g.,
NCCL WARNorTimeout) usually indicate a network or configuration issue between GPUs or nodes. SetNCCL_DEBUG=INFOto get verbose output that points to the root cause: - Process group not destroyed. Add
dist.destroy_process_group()at the end of your training script to cleanly shut down distributed workers. - Batch size too small. With data-parallel training, the total batch is split across GPUs, so each GPU must receive at least one sample. If
batch_size < num_gpus, you'll get a zero-length tensor error.
Connectivity¶
ssh: connect to host ... Connection refused (or timeout)
A "connection refused" or timeout when SSH-ing to Unity almost always means a network issue. Unity's login nodes may not be reachable from all networks.
Fix:
- If your institution requires a VPN for off-campus access, connect to it first.
- Then SSH to
login.unityhpc.org.
If you're already on campus or VPN and still see this error, double-check the hostname (a typo is a common cause). The correct login node is:
If the hostname is correct and VPN is active, the cluster may be in maintenance. Check the Dartmouth Research Computing status page for announcements.
Permission denied (publickey)
This error means SSH authentication failed: the server rejected your key. Unity uses SSH key authentication, so this usually means your key isn't properly configured.
Fix — check each of these in order:
-
Is your private key added to the SSH agent?
If your Unity key isn't listed, add it: -
Is your public key uploaded to the Unity portal? Log in to https://unity.dartmouth.edu/, go to Account Settings > SSH Keys, and verify your public key is there.
-
Are file permissions correct? Your private key must be readable only by you:
-
Are you using the correct username format? Dartmouth users connect as
netid_dartmouth_edu, not just your NetID:
If none of these resolve the issue, try verbose mode (ssh -v ...) and contact hpc@umass.edu with the output.
Storage & Quota¶
I'm getting \"No space left on device\" or \"Disk quota exceeded\"
Both errors mean you've run out of storage in a particular filesystem: either the total space is full, or your personal quota has been reached. They are treated differently, so diagnose first:
df -h $HOME # how much of your home quota is used
ws_list # list your scratch workspaces and expiration dates
Common culprits hiding in home:
| Location | What fills it |
|---|---|
~/.cache/pip | pip download and wheel cache |
~/.cache/uv | uv package cache |
~/.local/lib/python*/ | pip user-install packages |
~/.conda/ | Conda environments and packages |
~/.matlab/ | MATLAB temp files and toolbox caches |
Solutions:
- Move caches to scratch. Set environment variables before installing (replace
/path/to/your/scratchwith your actual workspace path fromws_allocate; see Storage Fundamentals): - Create conda environments on scratch using
--prefix: - Purge old virtual environments you no longer use (
rm -rfthe.venvdirectory).
Tip
Visit the Dartmouth Research Computing storage docs for the official quota check command and instructions for requesting a quota increase.
My scratch files disappeared
Scratch storage (/scratch) is not backed up and is subject to automatic purge policies: files that haven't been accessed in a set number of days are deleted without warning to reclaim space for all users.
Danger
If files on scratch are gone, they are not recoverable. There is no recycle bin or backup for scratch.
Scratch is designed for active, intermediate working data: input files staged for a running job, temporary outputs being processed. It is not intended for long-term storage.
Best practice workflow:
- Copy inputs to scratch before the job starts.
- Run the job, writing outputs to scratch.
- Copy important results back to your work directory at the end of the job script:
If you need additional long-term storage, contact Research Computing and Data about requesting a project allocation.
I can't write to my home directory from a compute node
Home directories are NFS-mounted on all compute nodes and should always be accessible. If writes are failing, work through the likely causes in order:
-
Quota exceeded. Run
df -h $HOME. If you're at 100 %, writes will fail even if the NFS mount is healthy. Free up space or contact Research Computing and Data to request an increase. -
NFS timeout (transient). High load can cause brief NFS hangs. If the problem appeared suddenly and your quota is fine, wait a few minutes and try again. Resubmitting the job usually resolves it.
-
Permission issue. Verify that the directory you're writing to is owned by you and has write permission:
Warning
If the problem is persistent across multiple jobs and your quota is fine, contact Research Computing and Data at research.computing@dartmouth.edu. A stuck NFS mount requires admin intervention.
R¶
R package installation fails with compilation errors
Many R packages include C, C++, or Fortran code that must be compiled during installation. Errors like unable to find -lgdal, zlib.h: No such file or directory, or cannot find -lproj mean a required system library is missing from the build environment. The R package itself is fine.
Fix: load the relevant module before starting R or running install.packages():
module load gcc # most packages need a modern compiler
module load gdal # for sf, rgdal, terra and other spatial packages
module load hdf5 # for rhdf5, ncdf4
module load netcdf # for ncdf4, RNetCDF
Then install the package from within R normally. The loaded modules make the system headers and libraries visible to the compiler.
Tip
The R on the Cluster page has a table of common packages and the modules they require. Check there first before searching for the missing library manually.
If you can't identify the required module, paste the full compilation error into a message to Research Computing and Data. The library name is usually visible in the last few lines.
My R job uses only 1 core even though I requested multiple CPUs
Requesting --cpus-per-task=8 in your job script tells Slurm to reserve 8 cores, but R is single-threaded by default and will not automatically use those cores. You must write parallel code explicitly.
Common options:
| Approach | When to use |
|---|---|
parallel::mclapply() | Simple fork-based parallelism on a single node |
foreach + doParallel | Loop-style parallelism with a parallel backend |
future + furrr | Tidyverse-friendly, works across nodes too |
A minimal example with parallel::mclapply:
library(parallel)
ncores <- as.integer(Sys.getenv("SLURM_CPUS_PER_TASK"))
results <- mclapply(my_list, my_function, mc.cores = ncores)
Warning
Never use detectCores() without a limit. On a compute node, detectCores() returns the total number of physical cores on the machine, far more than your allocation. Use as.integer(Sys.getenv("SLURM_CPUS_PER_TASK")) instead so your code respects the resources you actually requested.
See the R batch job recipe for complete parallel job script templates.
MATLAB¶
MATLAB exits immediately with error code 1 (license error)
An immediate exit with error code 1 almost always means MATLAB cannot acquire a license token: either the license server is unreachable, or all tokens for your license type are currently checked out.
Diagnose: run a minimal MATLAB command interactively on a compute node:
If this produces a license error rather than the toolbox list, it is a license issue, not a code issue.
What to do:
- Try again later. License tokens are shared across all Dartmouth users. During peak hours (weekday mornings and afternoons) tokens may all be in use. Off-peak hours are usually much better.
- Check which toolboxes you actually need. Each licensed toolbox checks out a separate token. If your code calls functions from toolboxes you don't need, remove those calls to reduce license pressure.
- Contact support if persistent. If you consistently can't get a license at any hour, contact Research Computing and Data at research.computing@dartmouth.edu with the exact license error message from the MATLAB output.
See the MATLAB batch job recipe for license-aware job script patterns.
My MATLAB parpool job is slower than single-threaded
Parallel overhead is real: launching workers, serializing data, and coordinating results all take time. If each parallel task runs in milliseconds, the overhead dominates and parallelism hurts performance.
Rule of thumb: each parfor iteration (or parallel task) should take at least a few seconds of computation to make parallelism worthwhile. If your iterations are very fast, restructure so each worker handles a batch of iterations rather than a single one:
% Instead of parfor over 10,000 tiny tasks:
parfor i = 1:10000
result(i) = tiny_function(i); % too fast — overhead dominates
end
% Batch into chunks:
chunk_size = ceil(10000 / pool.NumWorkers);
parfor w = 1:pool.NumWorkers
idx = (w-1)*chunk_size+1 : min(w*chunk_size, 10000);
result(idx) = arrayfun(@tiny_function, idx); % each worker does real work
end
Also verify that workers are actually being created. Add an assertion after parpool:
pool = parpool(str2num(getenv('SLURM_CPUS_PER_TASK')));
assert(pool.NumWorkers > 1, 'Expected multiple workers but got %d', pool.NumWorkers);
Tip
Use tic / toc around both a serial and parallel version on a small input to measure the actual speedup before committing to a full parallel job. Many workloads are faster in serial than with a parpool of 4–8 workers.
Getting More Help¶
If your problem isn't listed here, contact Research Computing and Data at research.computing@dartmouth.edu or visit https://rc.dartmouth.edu.
When reaching out, include:
- The job ID (
squeue --meorsacctoutput) - The error message (paste from your
.errfile) - The relevant portion of your job script
- What you've already tried
This helps the support team diagnose your issue without needing to ask follow-up questions.