CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-google-zxing--core

Core barcode encoding/decoding library supporting 17 formats including QR Code, Data Matrix, Aztec, PDF 417, and various 1D barcodes

Pending
Overview
Eval results
Files

exception-handling.mddocs/reference/

Exception Handling

Exception hierarchy for handling various barcode processing failures. All reading exceptions extend ReaderException, while encoding exceptions use WriterException. Understanding exception types allows for appropriate error handling and user feedback in barcode scanning and generation applications.

Capabilities

ReaderException

Abstract base exception for all barcode reading failures. Never thrown directly - always thrown as one of the specific subclasses.

/**
 * Abstract base class for all barcode reading exceptions.
 * Subclasses indicate specific failure reasons:
 * - NotFoundException: No barcode found
 * - ChecksumException: Barcode found but checksum failed
 * - FormatException: Barcode found but format invalid
 *
 * Note: ReaderException deliberately does not fill in stack trace
 * for performance reasons in high-frequency scanning scenarios.
 */
public abstract class ReaderException extends Exception {
    // Protected constructor - only subclasses can be instantiated
    protected ReaderException();

    protected ReaderException(Throwable cause);

    // Stack trace is not filled for performance
    @Override
    public final synchronized Throwable fillInStackTrace();
}

NotFoundException

Thrown when no barcode is found in the image. Most common exception during barcode scanning. Indicates the detector could not locate a valid barcode pattern.

/**
 * Exception thrown when no barcode is found in an image.
 * This is the most common exception during scanning and typically
 * indicates:
 * - No barcode present in the image
 * - Barcode is too small, blurry, or damaged to detect
 * - Image quality is insufficient
 * - Wrong format being attempted (use POSSIBLE_FORMATS hint)
 *
 * Handling: Show "no barcode found" message or continue scanning.
 */
public final class NotFoundException extends ReaderException {
    private static final NotFoundException INSTANCE = new NotFoundException();

    private NotFoundException();

    /**
     * Gets the singleton instance (for performance).
     * @return Shared NotFoundException instance
     */
    public static NotFoundException getNotFoundInstance();
}

Usage Example:

import com.google.zxing.*;

try {
    Reader reader = new MultiFormatReader();
    Result result = reader.decode(bitmap);
    System.out.println("Found: " + result.getText());

} catch (NotFoundException e) {
    // No barcode detected - very common during scanning
    System.out.println("No barcode found in image");
    // Continue scanning or show message to user

} catch (ChecksumException | FormatException e) {
    // Barcode detected but couldn't be decoded
    System.out.println("Barcode found but unreadable");
}

ChecksumException

Thrown when a barcode is found but checksum validation fails. Indicates the barcode was detected but data integrity check failed due to damage or poor quality.

/**
 * Exception thrown when a barcode is found but checksum validation fails.
 * Indicates:
 * - Barcode was successfully located
 * - Pattern structure is valid
 * - But data has been corrupted or is incomplete
 *
 * Common causes:
 * - Physical damage to barcode
 * - Print quality issues
 * - Partial obscuration
 * - Insufficient error correction capacity
 *
 * Handling: Retry scan, request user to clean barcode,
 * or report damaged barcode.
 */
public final class ChecksumException extends ReaderException {
    private static final ChecksumException INSTANCE = new ChecksumException();

    private ChecksumException();

    /**
     * Gets the singleton instance (for performance).
     * @return Shared ChecksumException instance
     */
    public static ChecksumException getChecksumInstance();
}

Usage Example:

import com.google.zxing.*;

try {
    Reader reader = new MultiFormatReader();
    Result result = reader.decode(bitmap);

} catch (ChecksumException e) {
    // Barcode found but damaged
    System.out.println("Barcode is damaged or unreadable");
    System.out.println("Please clean the barcode and try again");
    // Could retry with TRY_HARDER hint

} catch (NotFoundException e) {
    // No barcode found
    System.out.println("No barcode detected");
}

FormatException

Thrown when a barcode is found but format rules are violated. Indicates structural problems with the barcode data that prevent decoding.

/**
 * Exception thrown when a barcode is found but violates format rules.
 * Indicates:
 * - Barcode pattern was detected
 * - But data structure is invalid for the format
 *
 * Common causes:
 * - Invalid character in barcode data
 * - Incorrect data length for fixed-length formats
 * - Invalid format version or configuration
 * - Corrupted metadata (version info, format info, etc.)
 *
 * Handling: Barcode is fundamentally invalid and cannot be decoded.
 * May indicate incorrectly generated barcode or wrong format assumption.
 */
public final class FormatException extends ReaderException {
    private static final FormatException INSTANCE = new FormatException();

    private FormatException();

    /**
     * Gets the singleton instance (for performance).
     * @return Shared FormatException instance
     */
    public static FormatException getFormatInstance();
}

Usage Example:

import com.google.zxing.*;

try {
    Reader reader = new MultiFormatReader();
    Result result = reader.decode(bitmap);

} catch (FormatException e) {
    // Barcode structure is invalid
    System.out.println("Barcode format is invalid");
    System.out.println("This barcode may be incorrectly generated");

} catch (ChecksumException e) {
    // Barcode is damaged
    System.out.println("Barcode is damaged");

} catch (NotFoundException e) {
    // No barcode
    System.out.println("No barcode found");
}

WriterException

Exception for barcode encoding failures. Indicates problems generating a barcode from input data.

Important: Many encoding validation errors throw IllegalArgumentException instead of WriterException. For example:

  • Empty or null strings → IllegalArgumentException
  • Invalid format-specific data (wrong EAN-8 length, etc.) → IllegalArgumentException
  • Other encoding failures (capacity exceeded, invalid characters) → WriterException
/**
 * Exception thrown when encoding a barcode fails.
 * Indicates:
 * - Input data cannot be encoded in requested format
 * - Configuration parameters are invalid
 * - Data exceeds format capacity
 *
 * Common causes:
 * - Invalid characters for format
 * - Data too long for format/settings
 * - Invalid hint combination
 * - Incorrect format specified
 *
 * Unlike ReaderException, WriterException includes stack traces
 * since encoding failures are less frequent and more critical.
 */
public class WriterException extends Exception {
    /**
     * Creates a WriterException.
     */
    public WriterException();

    /**
     * Creates a WriterException with a message.
     * @param message Error message
     */
    public WriterException(String message);

    /**
     * Creates a WriterException with a cause.
     * @param cause Underlying exception
     */
    public WriterException(Throwable cause);
}

Usage Example:

import com.google.zxing.*;

try {
    Writer writer = new QRCodeWriter();
    BitMatrix matrix = writer.encode(
        "Data to encode",
        BarcodeFormat.QR_CODE,
        300,
        300
    );
    // Convert matrix to image...

} catch (WriterException e) {
    // Encoding failed
    System.err.println("Failed to encode barcode: " + e.getMessage());

    // Common causes:
    // - Data too long for format
    // - Invalid characters
    // - Invalid hints

    e.printStackTrace();
}

Exception Handling Patterns

Basic Scanning Loop

import com.google.zxing.*;

public Result scanBarcode(BinaryBitmap bitmap) {
    try {
        Reader reader = new MultiFormatReader();
        return reader.decode(bitmap);

    } catch (NotFoundException e) {
        // Normal - no barcode in this frame
        return null;

    } catch (ChecksumException e) {
        // Barcode damaged - might succeed on retry
        System.out.println("Damaged barcode detected");
        return null;

    } catch (FormatException e) {
        // Invalid barcode structure
        System.out.println("Invalid barcode format");
        return null;
    }
}

Retry with TRY_HARDER

import com.google.zxing.*;
import java.util.*;

public Result scanWithRetry(BinaryBitmap bitmap) {
    Reader reader = new MultiFormatReader();

    // First attempt - fast
    try {
        return reader.decode(bitmap);
    } catch (NotFoundException e) {
        // Not found - try harder
    } catch (ChecksumException | FormatException e) {
        // Detected but bad - try harder
    }

    // Second attempt - with TRY_HARDER
    try {
        Map<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
        hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
        return reader.decode(bitmap, hints);

    } catch (NotFoundException | ChecksumException | FormatException e) {
        return null; // Give up
    }
}

User-Friendly Error Messages

import com.google.zxing.*;

public String getUserFriendlyMessage(Exception e) {
    if (e instanceof NotFoundException) {
        return "No barcode found. Please align camera with barcode.";

    } else if (e instanceof ChecksumException) {
        return "Barcode is damaged. Please clean and try again.";

    } else if (e instanceof FormatException) {
        return "Invalid barcode format. This barcode may be incorrectly generated.";

    } else if (e instanceof WriterException) {
        return "Failed to create barcode: " + e.getMessage();

    } else {
        return "Unknown error: " + e.getMessage();
    }
}

Encoding with Validation

import com.google.zxing.*;

public BitMatrix encodeWithValidation(String data, BarcodeFormat format)
        throws WriterException {

    // Validate input
    if (data == null || data.isEmpty()) {
        throw new WriterException("Data cannot be empty");
    }

    // Validate format-specific requirements
    if (format == BarcodeFormat.EAN_13 && !data.matches("\\d{12,13}")) {
        throw new WriterException("EAN-13 requires 12-13 digits");
    }

    try {
        Writer writer = new MultiFormatWriter();
        return writer.encode(data, format, 300, 300);

    } catch (WriterException e) {
        // Add context to error
        throw new WriterException(
            "Failed to encode " + format + ": " + e.getMessage(), e);
    }
}

Exception Frequency

Common (Expected)

  • NotFoundException: Very common during video scanning (most frames won't contain barcodes)
  • Handle gracefully, continue scanning

Occasional (Quality Issues)

  • ChecksumException: Occasional with poor print quality, damage, or difficult angles
  • Consider retry with TRY_HARDER hint

Rare (Data Problems)

  • FormatException: Rare, usually indicates invalid barcode generation
  • Log for debugging, inform user of invalid barcode

Development (Configuration Errors)

  • WriterException: Should only occur during development/testing
  • Fix data or configuration before deployment
  • IllegalArgumentException: Invalid parameters to API methods

Performance Considerations

Singleton Pattern:

  • ReaderException subclasses use singleton instances for performance
  • No stack traces are filled in (deliberate design choice)
  • In tight scanning loops, creating exceptions would be too expensive
  • This is why stack traces show limited information for reader exceptions

Catching Exceptions:

  • Catching NotFoundException is not expensive (very fast)
  • Design your scanning loop expecting NotFoundException on most frames
  • Only catch specific exceptions you need to handle differently
  • Catching generic Exception is not recommended (hides bugs)

WriterException:

  • Unlike reader exceptions, WriterException includes full stack traces
  • Encoding failures are rare and typically indicate bugs or invalid input
  • Performance is not critical since encoding happens once per barcode

Best Practices

Do:

  • Catch specific exception types (NotFoundException, ChecksumException, FormatException)
  • Treat NotFoundException as normal during scanning
  • Retry with TRY_HARDER for ChecksumException
  • Log FormatException for debugging invalid barcodes
  • Provide user-friendly error messages
  • Validate input before encoding to avoid WriterException

Don't:

  • Don't rely on ReaderException stack traces (they're empty for performance)
  • Don't treat NotFoundException as an error (it's expected)
  • Don't catch generic Exception (hides real bugs)
  • Don't retry indefinitely (set reasonable limits)
  • Don't ignore WriterException (indicates coding error)
  • Don't show raw exception messages to users

See Also

  • Core Reading and Writing - Reader methods throw these exceptions
  • Configuration Hints - TRY_HARDER hint for difficult scans
  • Image Processing - Image quality affects exception frequency
  • Result Handling - Successful decode produces Result, not exception

Install with Tessl CLI

npx tessl i tessl/maven-com-google-zxing--core@3.5.1

docs

index.md

tile.json