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.
-
Install IronQR with NuGet Package Manager
PM > Install-Package IronQR -
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); -
Deploy to test on your live environment
Start using IronQR in your project today with a free trial
Minimal Workflow (5 steps)
- Download the IronQR C# library for QR code checksum validation
- Load an image with
QrImageInput - Call
QrReader.Readto decode the image and run Reed-Solomon validation automatically - Check the result collection to confirm decoding succeeded, as an empty collection means failure
- Validate the decoded value against application requirements before passing it downstream
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.
: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
Output
The console shows the decoded value https://ironsoftware.com/, confirming that Reed-Solomon decoding succeeded and the payload was recovered intact.
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)
Camera Capture (JPEG)
: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))
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.
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.
: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
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.
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
- Error Correction Levels: write-time resilience and correction level configuration.
- Reading QR Codes How-To: input format options and read patterns.
- QrResult API Reference: complete property surface.
- Advanced Scan Examples: scan mode configurations.
View licensing options when ready for production.
Click here to download the complete ChecksumFaultToleranceTest console app project.

