Troubleshooting
Match the visible symptom, make the smallest change, and keep sensitive DICOM data, launch links, and access tokens out of public diagnostics.
The command is not found
Section titled “The command is not found”Confirm that the package and interpreter agree:
python -m pip show dcmview-pypython -m dcmview_py --versionIf the module works but dcmview does not, reopen the shell or add Python’s user scripts directory to PATH. Avoid installing repeated copies into different interpreters.
If the module cannot find a binary on an unsupported wheel platform, install a GitHub Release binary or source build and set DCMVIEW_BINARY to its absolute path. The wrapper requires a v0.2.0 or newer binary.
A source build is missing a prerequisite
Section titled “A source build is missing a prerequisite”v0.4.1 source builds require Rust 1.88 or later, Node.js 20.19 or later, npm, CMake, and a C++ toolchain for the statically linked CharLS codec.
rustc --versionnode --versionnpm --versioncmake --versionThe Cargo build compiles and embeds the Svelte frontend. DCMVIEW_SKIP_FRONTEND_BUILD=1 is only valid when frontend/dist/index.html already exists.
--tunnel is not recognized
Section titled “--tunnel is not recognized”v0.3.0 removed --tunnel, --tunnel-host, --tunnel-port, and the matching Python keywords. Remove them from scripts, dcmview.extraArgs, and view() calls. Then run the ssh -L command that dcmview prints at startup on your local machine, as described in Inspect a study over SSH.
No valid DICOM files are found
Section titled “No valid DICOM files are found”Check that the path exists and that the running user can read it. Directory scans recurse by default; remove --no-recursive if valid files live below the top level. Temporarily remove filters to distinguish unreadable input from readable-but-filtered objects. When every readable file was filtered out, the error names the active filters.
DICOMDIR is deliberately skipped because v0.4.1 does not parse the file-set hierarchy. Point the viewer at the directory containing ordinary DICOM instances.
Files are skipped or filtered
Section titled “Files are skipped or filtered”The terminal’s completed-scan summary separates loaded, skipped, and filtered counts and breaks skipped files down by reason, such as files without a DICOM preamble or unparsable DICOM. Explorer shows the number indexed while a scan is still running.
To see which files were skipped and why, run with debug logging. Each skipped path and its reason is written to standard error:
RUST_LOG=dcmview=debug dcmview ./studySkipped non-DICOM sidecar files are usually harmless. Filtered input is readable DICOM whose metadata did not satisfy every --filter predicate. Filter fields accept snake_case names or DICOM keywords; see the CLI reference.
The viewer opens before every file appears
Section titled “The viewer opens before every file appears”This is expected during progressive discovery. Wait until Explorer’s indexing message disappears and the terminal prints the completed-scan summary. The whole directory tree is walked before the first file is inspected, so on a very large tree the first file appears only after that walk.
The viewer exits after --timeout
Section titled “The viewer exits after --timeout”The idle clock starts only when the scan has finished, so a long scan never counts toward --timeout. After that, only API and browser requests reset the clock. A viewer left open without interaction still exits when the timeout passes; use a longer value or omit --timeout.
The port is already in use
Section titled “The port is already in use”Omit --port or pass zero to let the operating system choose:
dcmview --port 0 ./studyIf an SSH command depends on a fixed port, choose another value in both the viewer and forwarding command.
The browser does not open
Section titled “The browser does not open”The server can still be healthy when the operating system browser launch fails. Use:
dcmview --no-browser ./studyOpen the printed loopback URL manually, including its #token=… fragment. When the browser launch fails, dcmview says to open the launch URL manually and does not print the opener’s error text, which could contain the link. On a remote host, do not open the remote URL directly; follow the SSH forwarding guide.
The page says “This viewer needs its access link”
Section titled “The page says “This viewer needs its access link””The page was opened without the session’s access token, for example from a bookmark, a hand-typed http://127.0.0.1:<port>/, or a link copied without its fragment. Copy the full link, including #token=…, from the terminal where dcmview is running and paste it into the same tab.
After the viewer loads, the token is no longer in the address bar. Copying the address from a loaded tab therefore does not give a working link; copy it from the terminal.
The page says “The viewer restarted”
Section titled “The page says “The viewer restarted””The tab belongs to an earlier dcmview process that used the same address, so the token it holds is no longer valid. Each process generates a new token unless you fix it with DCMVIEW_TOKEN. Paste the new link from the terminal, including #token=…, into the same tab.
An API request returns 401
Section titled “An API request returns 401”Every API path, including /api/health and unknown routes, needs the session’s bearer token. Without a valid one the server answers 401 with the code unauthorized and WWW-Authenticate: Bearer.
- In a browser, open the complete launch link printed by the current process.
- In a script, read
base_urlandtokenfrom the--startup-jsonline, append the API path tobase_url, and sendAuthorization: Bearer <token>. In Python, usehandle.base_urlandhandle.token. - Do not append an API path after the
#token=…fragment of the launch URL. - A token in a query parameter or cookie does not authenticate.
- A token from an earlier process does not work unless you fixed it with
DCMVIEW_TOKEN.
The routes are an unsupported internal protocol.
Startup fails because of DCMVIEW_TOKEN or --no-token
Section titled “Startup fails because of DCMVIEW_TOKEN or --no-token”DCMVIEW_TOKEN must be non-empty and contain only A-Z a-z 0-9 - . _ ~. An invalid value stops startup, and the error does not echo it. Setting the variable together with --no-token is also a startup error, even when the variable is empty; unset it before using --no-token.
A Unix socket fails to start
Section titled “A Unix socket fails to start”--unix-socket reports the reason and exits. Match the message:
| Message | Fix |
|---|---|
| The directory is not owned by your effective user ID | Use a directory that your account owns. |
| The directory is group- or other-writable | Remove group and other write permission, or use another directory. A missing directory is created with mode 0700. |
| The directory cannot be created | Only the socket’s own directory is created; create its parent first. |
| The path exists and is not a socket | Choose another path. Regular files and symlinks are never replaced. |
| The socket is already in use | Another viewer is running on that path. Stop it or choose another path. |
| Locking failed | The filesystem does not support file locks, as on some network filesystems. Put the socket in a local directory such as one under $XDG_RUNTIME_DIR. |
| Unsupported platform | Socket mode exists on Linux and macOS only. Use the loopback port with SSH forwarding. |
A conflict with --host or --port |
Remove those options; socket mode does not bind a TCP port. |
If ssh -L 8080:<socket> user@host fails, check that both ends run OpenSSH 6.7 or newer, which is required to forward a Unix socket. If the local port is busy, change 8080 in both the command and the link you open. A forced kill can leave a stale socket; the next launch on that path replaces it.
Socket mode is not available from Python view() or in the VS Code extension. The extension reports that Unix socket launches are not supported when --unix-socket is in dcmview.extraArgs.
The status bar says the server cannot be reached
Section titled “The status bar says the server cannot be reached”The viewer reports a lost server in the status bar with a Retry action. Confirm that the dcmview process, and any SSH forwarding session, is still running, then choose Retry. If the same server answers, failed images and panels are requested again. If a new dcmview process now answers on the same address, its token differs, and the tab shows The viewer restarted: paste the new link from the terminal into the same tab. When both processes share a token fixed with DCMVIEW_TOKEN, or run with --no-token, the viewer instead reloads its file list from the new session rather than mixing data from both. A page left in the background checks the server when you return to it.
A frame reports that pixel data disagrees with the header
Section titled “A frame reports that pixel data disagrees with the header”Since v0.4.1, a compressed frame (JPEG, JPEG-LS, JPEG 2000, JPEG XL, or Deflated Image Frame Compression) is decoded only when its own compressed data declares the image its DICOM header describes: the same rows, columns, and samples per pixel, and a sample depth that fits Bits Allocated. A frame that declares another image answers 500 pixel_decode_failed with “pixel data disagrees with the header”. The file stays listed and its other frames display.
The file is inconsistent, usually because its header was edited after compression or the pixel data was replaced. Re-encode it with a tool that writes the header from the compressed data. Files that differ from their header only in Bits Stored, sign, colour transform, resolution levels, or chroma subsampling display as before.
An image reports unsupported transfer syntax
Section titled “An image reports unsupported transfer syntax”The object remains isolated and the viewer continues serving other files. Inspect its Transfer Syntax UID and compare it with v0.4.1 DICOM support.
Do not assume a browser can safely decode the original compressed fragment. dcmview requires a server-side display path and returns a controlled 422 error for unsupported syntax. A corrupt JPEG fragment is reported as a JPEG decode failure with the decoder’s reason rather than as an unsupported syntax.
Tags load but the image is missing
Section titled “Tags load but the image is missing”The object may be metadata-only, may lack Pixel Data, or may have an unsupported geometry, numeric precision, component layout, or photometric interpretation. Check the file’s support state and reason in Explorer.
Metadata-only objects remain useful for tags and reference navigation. A no-pixel frame request returns 404; unsupported display layouts return a controlled 422 error, and decode failures are request-scoped. A file deleted or moved after discovery returns 404 naming its path.
A slide label or overview image is unsupported in a masked session
Section titled “A slide label or overview image is unsupported in a masked session”This is expected. A session started with --mask does not show slide label and overview images, because they photograph the slide label with its identifiers. Explorer lists them as unsupported, and their frame requests return a controlled 403 error with the code masked. Tags remain available under the masking rules. To view the image, start the viewer again without --mask.
Identifiers are still visible in a masked session
Section titled “Identifiers are still visible in a masked session”--mask is a display aid, not de-identification, and it does not cover everything on screen:
- Text burned into the pixels stays visible. Cover it with the Redact tool (
X). - Kept free-text values, such as Study and Series Description, can contain names or dates.
- Explorer’s Directory view shows real folder and file names under a Not masked note, and tabs follow that view while it is showing. Switch Explorer to the Study and Series view.
- The terminal, VS Code’s Explorer and custom-editor tabs, and the exported ROI CSV are outside the viewer page and keep real names and paths.
See Share your screen.
Redaction boxes are gone after a restart
Section titled “Redaction boxes are gone after a restart”Redaction boxes live in server memory for one session. They are not saved, loaded, or included in Export ROIs, so draw them again after you restart the viewer.
The pixel readout says a value is unavailable
Section titled “The pixel readout says a value is unavailable”The readout keeps row, column, and frame, but reports that the value is unavailable when the server cannot serve the frame’s raw samples, for example for an unsupported raw component layout. A real-world value appears only when the frame has a validated Real World Value Mapping or RT Dose Grid Scaling.
A real-world window falls back to the default window
Section titled “A real-world window falls back to the default window”A window in the unit of a LUT mapping, or of a mapping behind a Modality LUT, is exact on the server only for 8-bit, 16-bit, and one-bit single-sample frames. Server-rendered frames with other samples, or whose preferred mapping has a different unit, are shown with their default window, and the HUD shows that window instead of the unit window. See DICOM and pixel support.
A remote viewer is unreachable
Section titled “A remote viewer is unreachable”Confirm all three addresses:
dcmviewprinted the expected remote loopback port.- The SSH command forwards to that exact remote port.
- The browser opens the chosen local port with the printed
#token=…fragment.
Run the ssh -L command on your local machine, not on the remote server. Keep the remote server bound to 127.0.0.1. If a local port is busy, change only the first -L port and the port in the local browser URL, and keep the fragment.
Behind a reverse proxy that serves the viewer under a path prefix, the proxy must strip the prefix before forwarding and serve the page with a trailing slash, such as .../8888/. The API still requires the token through the proxy unless dcmview was started with --no-token.
VS Code opens a webview unexpectedly
Section titled “VS Code opens a webview unexpectedly”A launch opens in VS Code when it runs in a VS Code integrated terminal, or when its working directory is inside an open workspace folder. This applies to dcmview, dcmview-py, python -m dcmview_py, and dcmview_py.view(). Force one ordinary local launch:
export DCMVIEW_VSCODE_BYPASS=1dcmview ./studyIn Python, pass vscode_bridge=False. To stop terminal interception, disable dcmview.terminalInterception.enabled and create a new terminal.
Launches stop opening in VS Code
Section titled “Launches stop opening in VS Code”Update the extension. The v0.3.0 binary no longer searches the bridge registry locations used by extension builds older than 0.2.5. Then confirm that the launch runs in an integrated terminal created after activation or inside an open workspace folder, and check dcmview: Show Bridge Status. Set DCMVIEW_VSCODE_BRIDGE_DEBUG=1 to print bridge discovery diagnostics to standard error.
VS Code cannot start the viewer
Section titled “VS Code cannot start the viewer”Check dcmview: Show Bridge Status, then inspect dcmview.binaryPath. The extension otherwise tries the repository debug binary, its bundled platform binary, and PATH.
Verify that dcmview.extraArgs contains separate option/value elements, no removed --tunnel options, no --unix-socket, and no stale paths. Increase dcmview.startupTimeoutSeconds only when the process is healthy but slow to report its URL.
On an unsupported platform, supply an absolute compatible binary path.
The VS Code viewer panel asks for its access link
Section titled “The VS Code viewer panel asks for its access link”Update the extension. An extension older than v0.4.0 pointed at a v0.4.0 binary through dcmview.binaryPath can lose the token when VS Code forwards the port, as with Remote-SSH. The v0.4.0 extension forwards the viewer’s origin and attaches the token afterwards.
A DCMVIEW_TOKEN exported in a terminal is not forwarded to a viewer the extension manages, so do not expect that value to authenticate requests to it.
Annotation CSV fails to load
Section titled “Annotation CSV fails to load”Confirm the required headers anon_dicom_path and ROI_coords. A JSON-valued CSV cell that contains a comma must be quoted. Then check:
[ymin, xmin, ymax, xmax]order with non-negative integer coordinates;- zero-based frame indices below the frame count;
- matching counts for coordinates and frame lists; and
num_ROI, when present, matching the coordinate count.
Path matching uses normalized absolute identity. Start dcmview from the expected directory when the CSV uses relative paths.
An invalid matching row prevents the CSV transaction from committing, but image viewing continues. Annotation reads and export report the import error.
Loading does not check that a box lies inside the image or that ymax and xmax exceed ymin and xmin. Such a box loads and is exported as written, but the viewer refuses to save an edit to a file whose boxes break either rule; correct the CSV and start again.
Export ROIs shows a failure notice
Section titled “Export ROIs shows a failure notice”The viewer reports a failed export in the page instead of leaving the browser on an error page. The usual cause is an annotation CSV whose import failed: fix the CSV as described above. If the server is no longer reachable, restore it and export again.
Report issues safely
Section titled “Report issues safely”Use synthetic fixtures, redacted logs, and minimal reproduction steps. Debug logs list file paths, so redact them before sharing. Do not attach DICOM files, screenshots, annotation CSVs, launch links, access tokens, paths, patient/study identifiers, hostnames, or institutional metadata unless fully de-identified and approved for public sharing. Report suspected vulnerabilities privately.