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

QR codes embed Reed-Solomon error correction at the encoding level — the checksum and parity data are baked into the symbol itself, not into the reading API. When QrReader.Read() returns a QrResult, the Reed-Solomon decoding has already succeeded. If the error correction cannot recover the data — due to excessive damage beyond the correction level's capacity — the QR code simply does not appear in the results. There is no "partially decoded" state.

This means fault tolerance in IronQR operates at two boundaries: the error correction level chosen at write time (which determines how much physical damage the symbol can tolerate), and the validation logic applied at read time (which determines whether the decoded data meets application requirements before downstream use).

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

How to Validate QR Code Checksums?

QR codes use Reed-Solomon error correction to detect and repair damage to the encoded data. The correction level — Low (7%), Medium (15%), Quartile (25%), or High (30%) — determines what percentage of codewords can be lost and still be recovered. This is set at generation time via QrOptions and the error correction how-to covers the configuration in detail.

On the reading side, the checksum validation happens internally during decoding. IronQR's ML-powered scanner locates the QR symbol, extracts the data modules, runs the Reed-Solomon decode, and either succeeds or discards the result. The QrResult class does not expose a .Confidence property — if a result exists in the returned IEnumerable<QrResult>, the checksum passed. If decoding failed, the collection is empty.

This binary outcome — decoded or not — is the practical checksum validation. The application-level concern shifts from "did the checksum pass?" to "is the decoded data what the application expects?"

: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

For systems that need higher recoverability from physical damage, the solution is to generate QR codes with a higher error correction level. The error correction how-to demonstrates setting QrErrorCorrectionLevel.High via QrOptions — this recovers up to 30% data loss at the cost of a larger symbol.

How to Handle Format Awareness in QR Code Reading?

IronQR supports three QR encoding formats: standard QRCode, MicroQRCode, and RMQRCode (Rectangular Micro QR). The scanner detects the format automatically during the read — no configuration is required to handle different types. After scanning, the QrResult.QrType field exposes the detected format as a QrEncoding enum value.

The QrImageInput wrapper accepts multiple input types. We can construct it from a file path string, an AnyBitmap, a byte[], or a Stream. For PDFs, use QrPdfInput. The scan mode can also be specified: QrScanMode.Auto combines ML detection with classic scanning for maximum reliability, OnlyDetectionModel uses just the ML model for faster throughput, and OnlyBasicScan skips ML entirely for high-quality pre-processed images.

: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

The .QrType field is useful when the application expects a specific format. For instance, a warehouse system that only produces standard QR codes can filter out unexpected MicroQRCode or RMQRCode detections that might represent noise or unrelated labels in the image. Each format has different capacity characteristics: standard QR supports up to 7,089 numeric characters, MicroQR handles up to 35, and RMQRCode offers a rectangular form factor for constrained label spaces. The reading QR codes tutorial covers additional input scenarios including multi-frame TIFFs and PDF pages.

How to Apply Null Checking to QR Code Results?

QrReader.Read() returns IEnumerable<QrResult>. The collection is empty when no QR codes are found — it is not null. However, individual QrResult properties still need validation: .Value is a readonly string that could theoretically be empty, and .Url returns null when the value is not a valid URI. The .Points array contains the corner coordinates and is populated for every result.

The defensive pattern checks three things: collection count, individual .Value integrity, and type/URI validity before handing data off to another system.

: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

The validator returns an empty list (never null), which eliminates null-checking at the call site. The optional expectedFormat parameter acts as a format gate — the calling code only receives results matching the expected QrEncoding. For the .Url property, the null-conditional operator (?.) safely handles both URI and non-URI payloads.

For async workflows, the same patterns apply to QrReader.ReadAsync() — the return type is Task<IEnumerable<QrResult>>, so await the call and apply identical guards on the unwrapped collection.

Next Steps

QR code fault tolerance spans two layers: the Reed-Solomon error correction level set at generation time, and the application-level validation applied after reading. Use the error correction how-to to configure write-time resilience, and the patterns above to validate read-time results before they enter downstream systems.

Explore the QrResult API reference for the complete property surface, the reading how-to for input format options, and the code examples for advanced scan configurations.

View licensing options starting at $499.

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 60,166 | Version: 2026.3 just released
Still Scrolling Icon

Still Scrolling?

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