How to Validate QR Code Checksums and Apply Fault Tolerance in C#

QR code pipelines that process real-world inputs, including printed labels, camera captures, or scanned documents, will encounter symbols that are too damaged to decode and results that pass the checksum but fail business validation.

Reed-Solomon error correction automatically addresses physical damage during decoding. If a symbol cannot be recovered, the result collection is empty rather than partial. Application-level validation is separate and involves checking that the decoded value is non-empty, matches the expected format, or contains a valid URI before further processing.

This how to explains how to validate QR code checksums and apply fault tolerance checks with the IronQR library.

Quickstart: Validate QR Code Checksums

Read a QR code and check whether decoding succeeded: a non-empty result means the Reed-Solomon checksum passed.

  1. Install IronQR with NuGet Package Manager

    PM > Install-Package IronQR
  2. Copy and run this code snippet.

    using IronQr;
    using IronSoftware.Drawing;
    
    var reader = new QrReader();
    IEnumerable<QrResult> results = reader.Read(new QrImageInput("label.png"));
    
    if (!results.Any())
    {
        Console.WriteLine("No QR code detected or decoding failed.");
        return;
    }
    
    Console.WriteLine(results.First().Value);
  3. Deploy to test on your live environment

    Start using IronQR in your project today with a free trial

    arrow pointer

Validating QR Code Checksums

QR codes use Reed-Solomon error correction to detect and repair damage to the encoded data. The correction level (Low at 7%, Medium at 15%, Quartile at 25%, or High at 30%) determines the percentage of codewords that can be lost and still be recovered.

On the reading side, checksum validation runs internally during decoding. The QrResult class does not expose a confidence property; if a result exists in the collection, the checksum passed. If decoding fails, the collection is empty.

Input

A QR code product label encoding https://ironsoftware.com/, generated with Medium error correction, representing a label that may have been handled or lightly scratched in transit.

QR code encoding https://ironsoftware.com used as input for checksum validation
:path=/static-assets/qr/content-code-examples/how-to/checksum-and-fault-tolerance/checksum-validation.cs
using IronQr;
using IronSoftware.Drawing;

var reader = new QrReader();
IEnumerable<QrResult> results = reader.Read(new QrImageInput("damaged-label.png"));

// Reed-Solomon decoding is pass/fail — presence in results means valid checksum
if (!results.Any())
{
    // Decoding failed entirely — damage exceeded the error correction capacity
    Console.WriteLine("QR code could not be decoded. Consider re-scanning or using a higher error correction level at generation time.");
    return;
}

foreach (QrResult result in results)
{
    // Decoded successfully — validate the content matches expected format
    if (string.IsNullOrWhiteSpace(result.Value))
    {
        Console.WriteLine("QR decoded but produced an empty value.");
        continue;
    }

    Console.WriteLine($"Valid QR: {result.Value}");
}
Imports IronQr
Imports IronSoftware.Drawing

Dim reader As New QrReader()
Dim results As IEnumerable(Of QrResult) = reader.Read(New QrImageInput("damaged-label.png"))

' Reed-Solomon decoding is pass/fail — presence in results means valid checksum
If Not results.Any() Then
    ' Decoding failed entirely — damage exceeded the error correction capacity
    Console.WriteLine("QR code could not be decoded. Consider re-scanning or using a higher error correction level at generation time.")
    Return
End If

For Each result As QrResult In results
    ' Decoded successfully — validate the content matches expected format
    If String.IsNullOrWhiteSpace(result.Value) Then
        Console.WriteLine("QR decoded but produced an empty value.")
        Continue For
    End If

    Console.WriteLine($"Valid QR: {result.Value}")
Next
$vbLabelText   $csharpLabel

Output

The console shows the decoded value https://ironsoftware.com/, confirming that Reed-Solomon decoding succeeded and the payload was recovered intact.

Terminal output showing Decoded QR Code: https://ironsoftware.com

For greater resilience to physical damage, generate QR codes with a higher error correction level. The High level recovers up to 30% data loss at the cost of a larger symbol.


Handling Format Awareness in QR Code Reading

IronQR supports three QR encoding formats: standard QR, Micro QR, and Rectangular Micro QR. The scanner automatically detects the format during reading. After scanning, the QrResult.QrType field provides the detected format as an enum value.

For PDFs, use QrPdfInput instead of QrImageInput. Scan mode determines the balance between speed and accuracy: Auto combines machine learning detection with a classic scan, OnlyDetectionModel uses only the ML model for faster processing, and OnlyBasicScan skips ML entirely for high-quality pre-processed images.

Input

A PNG product label (left) and a JPEG camera capture (right), demonstrating format-aware reading across two common input types.

product-label.png QR code used as input for format-aware reading
camera-capture.jpg JPEG QR code simulating a camera capture
:path=/static-assets/qr/content-code-examples/how-to/checksum-and-fault-tolerance/format-awareness.cs
using IronQr;
using IronSoftware.Drawing;
using IronQr.Enum;

// Read from an image file with ML + classic scan (default)
var reader = new QrReader();
IEnumerable<QrResult> results = reader.Read(new QrImageInput("product-label.png"));

foreach (QrResult result in results)
{
    // Inspect the detected QR format
    Console.WriteLine($"Format: {result.QrType}");   // QRCode, MicroQRCode, or RMQRCode
    Console.WriteLine($"Value:  {result.Value}");

    // Url is non-null only if Value is a valid URI
    if (result.Url != null)
    {
        Console.WriteLine($"URI:    {result.Url.AbsoluteUri}");
    }

    // Corner coordinates for positional context
    Console.WriteLine($"Corners: {result.Points.Length} points detected");
}

// Read from a bitmap with ML-only mode for faster throughput
var bitmap = AnyBitmap.FromFile("camera-capture.jpg");
var fastResults = reader.Read(new QrImageInput(bitmap, QrScanMode.OnlyDetectionModel));
Imports IronQr
Imports IronSoftware.Drawing
Imports IronQr.Enum

' Read from an image file with ML + classic scan (default)
Dim reader As New QrReader()
Dim results As IEnumerable(Of QrResult) = reader.Read(New QrImageInput("product-label.png"))

For Each result As QrResult In results
    ' Inspect the detected QR format
    Console.WriteLine($"Format: {result.QrType}")   ' QRCode, MicroQRCode, or RMQRCode
    Console.WriteLine($"Value:  {result.Value}")

    ' Url is non-null only if Value is a valid URI
    If result.Url IsNot Nothing Then
        Console.WriteLine($"URI:    {result.Url.AbsoluteUri}")
    End If

    ' Corner coordinates for positional context
    Console.WriteLine($"Corners: {result.Points.Length} points detected")
Next

' Read from a bitmap with ML-only mode for faster throughput
Dim bitmap As AnyBitmap = AnyBitmap.FromFile("camera-capture.jpg")
Dim fastResults = reader.Read(New QrImageInput(bitmap, QrScanMode.OnlyDetectionModel))
$vbLabelText   $csharpLabel

Output

The console shows the detected format, decoded value, resolved URI, and corner count for the product label, followed by the fast-scan result count for the camera capture.

Terminal output showing Format: QRCode, Value: https://ironsoftware.com/product, URI, and Corners: 4 points detected

The QrType field is helpful when the application requires a specific format. For example, a warehouse system that produces only standard QR codes can filter out unexpected Micro QR or Rectangular Micro QR detections, which may indicate noise or unrelated labels. Each format has distinct capacity characteristics: standard QR supports up to 7,089 numeric characters, Micro QR up to 35, and Rectangular Micro QR provides a rectangular form factor for limited label space.


Applying Null Checks to QR Code Results

QrReader.Read returns an empty collection if no QR codes are found; it never returns null. However, individual result properties still require validation. For example Value may be empty, and Url returns null if the decoded string is not a valid URI.

A robust validation pattern checks three aspects: collection count, value integrity, and type or URI validity before passing data to another system.

Input

A blank white image with no QR code, representing a document page in a mixed batch where some pages carry no machine-readable label.

Blank white image with no QR code used as input for null checking demonstration
:path=/static-assets/qr/content-code-examples/how-to/checksum-and-fault-tolerance/null-checking-validator.cs
using IronQr;
using IronSoftware.Drawing;
using System.Collections.Generic;
using System.Linq;

public static class QrValidator
{
    public static List<QrResult> GetValidResults(
        string imagePath,
        QrEncoding? expectedFormat = null)
    {
        var reader = new QrReader();
        IEnumerable<QrResult> results = reader.Read(new QrImageInput(imagePath));

        // Guard: no QR codes detected
        if (!results.Any())
            return new List<QrResult>();

        return results
            .Where(r => !string.IsNullOrWhiteSpace(r.Value))
            .Where(r => expectedFormat == null || r.QrType == expectedFormat)
            .ToList();
    }
}

// Usage — only accept standard QR codes with non-empty values
var validated = QrValidator.GetValidResults(
    "shipping-manifest.png",
    expectedFormat: QrEncoding.QRCode);

if (validated.Count == 0)
{
    Console.WriteLine("No valid QR codes found for processing.");
    return;
}

foreach (var qr in validated)
{
    // Safe for downstream: value is non-empty, format is verified
    SendToInventoryApi(qr.Value, qr.Url?.AbsoluteUri);
}
Imports IronQr
Imports IronSoftware.Drawing
Imports System.Collections.Generic
Imports System.Linq

Public Module QrValidator
    Public Function GetValidResults(
        imagePath As String,
        Optional expectedFormat As QrEncoding? = Nothing) As List(Of QrResult)

        Dim reader As New QrReader()
        Dim results As IEnumerable(Of QrResult) = reader.Read(New QrImageInput(imagePath))

        ' Guard: no QR codes detected
        If Not results.Any() Then
            Return New List(Of QrResult)()
        End If

        Return results _
            .Where(Function(r) Not String.IsNullOrWhiteSpace(r.Value)) _
            .Where(Function(r) expectedFormat Is Nothing OrElse r.QrType = expectedFormat) _
            .ToList()
    End Function
End Module

' Usage — only accept standard QR codes with non-empty values
Dim validated = QrValidator.GetValidResults(
    "shipping-manifest.png",
    expectedFormat:=QrEncoding.QRCode)

If validated.Count = 0 Then
    Console.WriteLine("No valid QR codes found for processing.")
    Return
End If

For Each qr In validated
    ' Safe for downstream: value is non-empty, format is verified
    SendToInventoryApi(qr.Value, qr.Url?.AbsoluteUri)
Next qr
$vbLabelText   $csharpLabel

Output

The console displays the validator's empty-result response: no QR codes were detected, so the collection is empty and no data proceeds to downstream processing.

Terminal output showing No valid QR codes found for processing.

The validator returns an empty list (never null), eliminating the need for null-checking at the call site. The optional expectedFormat parameter acts as a format gate, so the calling code receives only results that match the expected format type. The Url property uses the null-conditional operator to safely handle both URI and non-URI payloads.

For asynchronous workflows, apply the same validation patterns to ReadAsync: await the call and use identical checks on the resulting collection.


Further Reading

View licensing options when ready for production.

Click here to download the complete ChecksumFaultToleranceTest console app project.

Curtis Chau
Technical Writer

Curtis Chau holds a Bachelor’s degree in Computer Science (Carleton University) and specializes in front-end development with expertise in Node.js, TypeScript, JavaScript, and React. Passionate about crafting intuitive and aesthetically pleasing user interfaces, Curtis enjoys working with modern frameworks and creating well-structured, visually appealing manuals.

...

Read More
Ready to Get Started?
Nuget Downloads 63,022 | Version: 2026.4 just released
Still Scrolling Icon

Still Scrolling?

Want proof fast? PM > Install-Package IronQR
run a sample watch your URL become a QR code.