Skip to main content

Error Handling

PDFixa throws standard Java exceptions. There are no custom exception hierarchies to learn — you handle IllegalArgumentException for bad inputs and IOException for output failures.

Exception summary

ExceptionWhen thrownTypical cause
IllegalArgumentExceptionImmediately on the bad callNegative dimensions, null text, unregistered font
IOExceptionDuring writeToStream closed, disk full, network error
IOExceptionDuring registerFontCorrupt or unreadable font file
NullPointerExceptionOn any methodPassing null where a value is required

Invalid coordinates and dimensions

Page dimensions and draw coordinates must be non-negative. Negative or zero values throw IllegalArgumentException:

try (PdfDocument doc = new PdfDocument()) {
// Negative page width → IllegalArgumentException
doc.addPage(-100, 842);
}
PdfPage page = doc.addPage(595, 842);

// Negative text box width → IllegalArgumentException
page.drawTextBox(72, 750, -200, 40, "Hello");

Coordinates outside the page (e.g. x = 1000 on a 595-wide page) are valid — the content is simply clipped or not visible. PDFixa does not enforce page bounds.

Defensive pattern

void drawSafe(PdfPage page, double x, double y, double w, double h, String text) {
if (w <= 0 || h <= 0) {
return;
}
page.drawTextBox(x, y, w, h, text);
}

Font loading failures

doc.registerFont(byte[]) throws IOException if the byte array is not a valid TrueType or OpenType font:

try {
PdfFont font = doc.registerFont(fontBytes);
} catch (IOException e) {
// Corrupt font file, truncated download, wrong format
log.error("Failed to load font: {}", e.getMessage());
throw e;
}

Common causes:

SymptomCauseFix
IOException on startupFont file not found on classpathVerify path in getResourceAsStream
IOException mid-streamTruncated or corrupt .ttf fileRe-download or validate the file
Garbled text in PDFWrong font file (e.g. .woff instead of .ttf)Use .ttf or .otf format

Safe font loading from classpath

static PdfFont loadFont(PdfDocument doc, String resourcePath) throws IOException {
try (InputStream in = MyClass.class.getResourceAsStream(resourcePath)) {
if (in == null) {
throw new IOException("Font resource not found: " + resourcePath);
}
return doc.registerFont(in.readAllBytes());
}
}
PdfFont bold = loadFont(doc, "/fonts/Inter-Bold.ttf");

I/O errors during writeTo

doc.writeTo(OutputStream) throws IOException if the underlying stream fails:

try (PdfDocument doc = new PdfDocument();
FileOutputStream out = new FileOutputStream("report.pdf")) {

PdfPage page = doc.addPage(595, 842);
page.drawTextBox(72, 750, 450, 40, "Hello");

doc.writeTo(out);

} catch (IOException e) {
log.error("Failed to write PDF: {}", e.getMessage());
// Disk full, permission denied, stream closed
}

HTTP response errors

When writing to HttpServletResponse, the client may disconnect mid-transfer:

try (PdfDocument doc = new PdfDocument()) {
PdfPage page = doc.addPage(595, 842);
page.drawTextBox(72, 750, 450, 40, "Report content");

doc.writeTo(response.getOutputStream());

} catch (IOException e) {
// Client disconnected — log and move on
log.warn("PDF delivery interrupted: {}", e.getMessage());
}

Null arguments

Passing null where a value is required throws NullPointerException:

page.drawTextBox(72, 750, 450, 40, null);           // NPE — null text
page.drawTextBox(72, 750, 450, 40, "ok", null, 12); // NPE — null font

Guard with a simple check when input comes from external data:

String title = Optional.ofNullable(report.title()).orElse("Untitled");
page.drawTextBox(72, 750, 450, 40, title, boldFont, 14);

Complete try/catch template

A production-ready pattern that handles all three exception types:

public byte[] generateReport(ReportData data) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();

try (PdfDocument doc = new PdfDocument()) {
PdfFont font = loadFont(doc, "/fonts/Inter-Regular.ttf");

doc.setTitle(data.title());
PdfPage page = doc.addPage(595, 842);
page.drawTextBox(72, 750, 450, 40, data.title(), font, 16);

doc.writeTo(buffer);

} catch (IllegalArgumentException e) {
throw new ReportException("Invalid report parameters", e);

} catch (IOException e) {
throw new ReportException("PDF generation I/O failure", e);
}

return buffer.toByteArray();
}

The try-with-resources ensures PdfDocument is always closed, even when an exception occurs. Wrap in your application-specific exception for clean API boundaries.