conductor-oss/conductor · error · RuntimeException

Failed to generate PDF from markdown

Error message

Failed to generate PDF from markdown

What it means

Thrown by MarkdownToPdfConverter.convert when PDFBox (PDDocument / PDPageContentStream) raises an IOException during rendering or document.save(). The converter catches IOException specifically and wraps it as a RuntimeException with a generic message, preserving the cause. Indicates a failure in the PDF generation pipeline: font issues, content-stream errors, image encoding failures, or output-stream problems.

Source

Thrown at ai/src/main/java/org/conductoross/conductor/ai/pdf/MarkdownToPdfConverter.java:105

                            compact);

            // Step 6: Render AST to PDF
            PdfDocumentRenderer renderer =
                    new PdfDocumentRenderer(ctx, imageResolver, request.getImageBaseUrl());
            renderer.render(markdownAst);

            // Step 7: Close the last content stream
            if (ctx.getContentStream() != null) {
                ctx.getContentStream().close();
            }

            // Step 8: Save to bytes
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            document.save(out);
            return out.toByteArray();

        } catch (IOException e) {
            throw new RuntimeException("Failed to generate PDF from markdown", e);
        }
    }

    private Document parseMarkdown(String markdown) {
        MutableDataSet options = new MutableDataSet();
        options.set(
                Parser.EXTENSIONS,
                List.of(
                        TablesExtension.create(),
                        StrikethroughExtension.create(),
                        TaskListExtension.create(),
                        FootnoteExtension.create(),
                        AutolinkExtension.create(),
                        DefinitionExtension.create()));

        Parser parser = Parser.builder(options).build();
        return parser.parse(markdown);
    }

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Inspect e.getCause() (the IOException) — its message names the exact PDFBox failure.
  2. If the cause is image-related, validate/resolve images before convert() and remove or convert unsupported formats.
  3. If font-related, ensure required fonts are available or embed them.
  4. Reproduce with a minimal markdown sample to isolate which element (image, table, code block) triggers it.

Example fix

// before
byte[] pdf = converter.convert(req);
// after
try {
    byte[] pdf = converter.convert(req);
} catch (RuntimeException e) {
    if (e.getCause() instanceof java.io.IOException io) {
        log.error("PDFBox failure rendering markdown: {}", io.getMessage(), io);
    }
    throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate images/fonts referenced in the markdown before convert.
// Ensure imageResolver can resolve every ![](url) and required fonts are present.

Try / catch

try {
    byte[] pdf = converter.convert(request);
} catch (RuntimeException e) {
    Throwable root = e.getCause();
    if (root instanceof java.io.IOException io) {
        log.error("PDFBox IOException: {}", io.getMessage(), io);
    }
    throw e;
}

Prevention

When it happens

Trigger: An image referenced in the markdown cannot be resolved/encoded by the imageResolver; a font required for the text is missing; content-stream operations fail (e.g. page is full, matrix error); document.save() fails (disk full, encoding error); malformed markdown AST triggers a rendering path PDFBox rejects.

Common situations: Broken/unsupported image format in markdown; missing font on the server; very large document exhausting memory; a content-stream state bug during multi-page rendering; transient I/O error writing the ByteArrayOutputStream (rare).

Related errors


AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14). Data as JSON: /api/errors/5a51c4665f53f0a1. Report an issue: GitHub.