PACS and DICOM Troubleshooting Guide

Section 23 of 27
85% complete

This guide covers the most common issues PACS administrators encounter.

Issue #1: Association Rejected - AE Title Not Recognized

Symptom: Modality cannot connect to PACS. Error: “Association rejected” or “Called AE Title not found”

Root Causes:

  • AE Title mismatch (case-sensitive)
  • AE Title not configured in PACS
  • Extra spaces in AE Title
  • Maximum length exceeded (16 characters)

Resolution:

public class AETitleValidator
{
    public void ValidateAndFix(string aeTitle)
    {
        Console.WriteLine($"Validating AE Title: '{aeTitle}'");

        // Check 1: Length
        if (aeTitle.Length > 16)
        {
            Console.WriteLine($"AE Title too long: {aeTitle.Length} chars (max 16)");
            Console.WriteLine($"Fix: Truncate to: '{aeTitle.Substring(0, 16)}'");
        }

        // Check 2: Leading/trailing spaces
        if (aeTitle != aeTitle.Trim())
        {
            Console.WriteLine("Leading or trailing spaces detected");
            Console.WriteLine($"Fix: Use '{aeTitle.Trim()}'");
        }

        // Check 3: Valid characters
        if (!System.Text.RegularExpressions.Regex.IsMatch(aeTitle, @"^[A-Z0-9_ ]+$"))
        {
            Console.WriteLine("Invalid characters detected");
            Console.WriteLine("AE Titles should only contain: A-Z, 0-9, space, underscore");
        }
        else
        {
            Console.WriteLine("AE Title format is valid");
        }
    }
}

PACS Configuration Steps:

  1. Log into PACS administration console
  2. Navigate to Network Configuration - Remote AE Titles
  3. Add the AE Title exactly as it appears on the device
  4. Verify IP address is correct
  5. Test connection using C-ECHO

Issue #2: Images Not Arriving at PACS

Symptom: Modality reports successful send, but images don’t appear in PACS

Root Causes:

  • Network packet loss
  • Firewall blocking return traffic
  • PACS storage full
  • Routing rules filtering the study

Diagnostic Script:

public class ImageArrivalDiagnostics
{
    public void Diagnose(string modalityAE, string pacsAE, string pacsHost, int pacsPort)
    {
        Console.WriteLine("=== Image Arrival Diagnostics ===\n");

        // Test 1: C-ECHO
        Console.WriteLine("1. Testing connectivity (C-ECHO)...");
        var echoService = new DicomVerificationService();
        bool echoSuccess = echoService.PerformEcho(modalityAE, pacsAE, pacsHost, pacsPort);

        if (!echoSuccess)
        {
            Console.WriteLine("C-ECHO failed - no connectivity");
            return;
        }
        Console.WriteLine("C-ECHO successful\n");

        // Test 2: Send test image
        Console.WriteLine("2. Sending test image...");
        string testImage = CreateTestImage();
        var storageService = new DicomStorageService();
        bool storeSuccess = storageService.StoreImage(
            modalityAE, pacsAE, pacsHost, pacsPort, testImage);

        if (!storeSuccess)
        {
            Console.WriteLine("C-STORE failed - check PACS logs");
            return;
        }
        Console.WriteLine("C-STORE successful\n");

        // Test 3: Query for the test image
        Console.WriteLine("3. Querying PACS for test image...");
        System.Threading.Thread.Sleep(5000); // Wait for processing

        var queryService = new DicomQueryService();
        var results = queryService.QueryStudies(
            modalityAE, pacsAE, pacsHost, pacsPort,
            patientName: "TEST^CONNECTIVITY"
        );

        if (results.Count > 0)
        {
            Console.WriteLine("Test image found in PACS");
            Console.WriteLine("Issue is likely with specific studies or routing rules");
        }
        else
        {
            Console.WriteLine("Test image NOT found");
            Console.WriteLine("Possible causes:");
            Console.WriteLine("  - PACS routing rules filtering");
            Console.WriteLine("  - Database synchronization delay");
        }
    }

    private string CreateTestImage()
    {
        var creator = new DicomFileCreator();
        var ds = creator.CreateCTImage("TEST^CONNECTIVITY", "CONNTEST001");
        string testFile = Path.Combine(Path.GetTempPath(), "test.dcm");
        creator.SaveDicomFile(ds, testFile);
        return testFile;
    }
}

Issue #3: Study Locked or In Use Error

Symptom: Cannot modify, delete, or re-send study. Error: “Study is locked”

Root Causes:

  • Active query or retrieval operation
  • Failed transaction not rolled back
  • Orphaned lock from crashed process

Resolution Script:

public class StudyLockResolver
{
    private SqlConnection dbConnection;

    public void ResolveLock(string studyInstanceUID)
    {
        Console.WriteLine($"Resolving lock for study: {studyInstanceUID}\n");

        var locks = CheckActiveLocks(studyInstanceUID);

        if (locks.Count == 0)
        {
            Console.WriteLine("No active locks found");
            return;
        }

        Console.WriteLine($"Found {locks.Count} active lock(s):");

        foreach (var lockInfo in locks)
        {
            Console.WriteLine($"\nLock ID: {lockInfo.LockId}");
            Console.WriteLine($"Process: {lockInfo.ProcessName}");
            Console.WriteLine($"Started: {lockInfo.StartTime}");
            Console.WriteLine($"Duration: {lockInfo.Duration}");

            // If lock is older than 5 minutes, likely orphaned
            if (lockInfo.Duration.TotalMinutes > 5)
            {
                Console.WriteLine("Lock appears orphaned (>5 minutes old)");
                Console.Write("Release this lock? (y/n): ");

                if (Console.ReadLine()?.ToLower() == "y")
                {
                    ReleaseLock(lockInfo.LockId);
                    Console.WriteLine("Lock released");
                }
            }
        }
    }

    private List<LockInfo> CheckActiveLocks(string studyInstanceUID)
    {
        var locks = new List<LockInfo>();

        string query = @"
            SELECT lock_id, process_name, lock_time,
                   DATEDIFF(MINUTE, lock_time, GETDATE()) as duration_minutes
            FROM study_locks
            WHERE study_instance_uid = @studyUID
            AND lock_status = 'ACTIVE'";

        using (var cmd = new SqlCommand(query, dbConnection))
        {
            cmd.Parameters.AddWithValue("@studyUID", studyInstanceUID);
            using (var reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    locks.Add(new LockInfo
                    {
                        LockId = reader.GetInt32(0),
                        ProcessName = reader.GetString(1),
                        StartTime = reader.GetDateTime(2),
                        Duration = TimeSpan.FromMinutes(reader.GetInt32(3))
                    });
                }
            }
        }
        return locks;
    }

    private void ReleaseLock(int lockId)
    {
        string query = @"
            UPDATE study_locks
            SET lock_status = 'RELEASED', release_time = GETDATE()
            WHERE lock_id = @lockId";

        using (var cmd = new SqlCommand(query, dbConnection))
        {
            cmd.Parameters.AddWithValue("@lockId", lockId);
            cmd.ExecuteNonQuery();
        }
    }
}

Issue #4: Duplicate Studies in PACS

Symptom: Same study appears multiple times

Root Causes:

  • Multiple sends from modality
  • Different accession numbers assigned
  • UID reuse (non-compliant device)

Detection Script:

public class DuplicateStudyDetector
{
    public void FindDuplicates(string patientID)
    {
        Console.WriteLine($"Searching for duplicates for Patient: {patientID}\n");

        var studies = GetPatientStudies(patientID);
        var potentialDuplicates = new List<List<StudyInfo>>();

        // Group by modality and date (within 1 hour)
        foreach (var study in studies)
        {
            var matchingGroup = potentialDuplicates.FirstOrDefault(g =>
                g.First().Modality == study.Modality &&
                Math.Abs((g.First().StudyDateTime - study.StudyDateTime).TotalHours) < 1
            );

            if (matchingGroup != null)
            {
                matchingGroup.Add(study);
            }
            else
            {
                potentialDuplicates.Add(new List<StudyInfo> { study });
            }
        }

        // Report duplicates
        var duplicateGroups = potentialDuplicates.Where(g => g.Count > 1);

        if (!duplicateGroups.Any())
        {
            Console.WriteLine("No potential duplicates found");
            return;
        }

        foreach (var group in duplicateGroups)
        {
            Console.WriteLine($"\n=== Potential Duplicate Group ===");
            Console.WriteLine($"Modality: {group.First().Modality}");
            Console.WriteLine($"Date: {group.First().StudyDateTime:yyyy-MM-dd}");

            foreach (var study in group)
            {
                Console.WriteLine($"  Study UID: {study.StudyInstanceUID}");
                Console.WriteLine($"    Accession: {study.AccessionNumber}");
                Console.WriteLine($"    Images: {study.NumberOfInstances}");
            }
        }
    }
}

Issue #5: Character Encoding Problems

Symptom: Patient names display incorrectly with garbled characters

Root Causes:

  • Missing Specific Character Set attribute
  • Incorrect character set specified
  • Encoding mismatch between systems

Resolution:

public class CharacterEncodingFixer
{
    public void FixEncoding(string inputFile, string outputFile)
    {
        DicomDataSet ds = new DicomDataSet();
        ds.Read(inputFile);

        // Check current character set
        string currentCharSet = ds[DicomTag.SpecificCharacterSet]?.Value?.ToString() ?? "";
        Console.WriteLine($"Current Character Set: '{currentCharSet}'");

        // Set to UTF-8 (ISO_IR 192)
        ds[DicomTag.SpecificCharacterSet].Value = "ISO_IR 192";

        // Re-encode string values if needed
        string patientName = ds[DicomTag.PatientName]?.Value?.ToString();
        if (!string.IsNullOrEmpty(patientName))
        {
            // Attempt to fix encoding issues
            byte[] bytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(patientName);
            string corrected = Encoding.UTF8.GetString(bytes);
            ds[DicomTag.PatientName].Value = corrected;
            Console.WriteLine($"Patient Name: {patientName} -> {corrected}");
        }

        ds.Write(outputFile);
        Console.WriteLine($"Fixed file saved to: {outputFile}");
    }
}

Common Character Sets:

CodeDescription
ISO_IR 100Latin alphabet No. 1
ISO_IR 101Latin alphabet No. 2
ISO_IR 192UTF-8
ISO 2022 IR 6ASCII
ISO 2022 IR 87Japanese (JIS X 0208)

Troubleshooting Summary

IssueFirst CheckCommon Fix
Association RejectedAE Title configurationAdd AE Title to remote system
Images MissingC-ECHO connectivityCheck firewall, routing rules
Study LockedLock table entriesRelease orphaned locks
Duplicate StudiesStudy matching criteriaMerge or delete duplicates
Character IssuesSpecific Character SetSet to ISO_IR 192 (UTF-8)

Systematic troubleshooting helps resolve PACS issues quickly and efficiently.

Quiz: PACS and DICOM Troubleshooting Guide

Question 1 of 4

What is the maximum length for a DICOM AE Title?