Pulp Engine Document Rendering
Get started
Release v0.41.0

Pulp Engine v0.41.0 — Release Notes

This release completes render error classification for the public API routes and sharpens the /render/validate contract, making all three render endpoints operationally honest and machine-readable.


What changed

1. Public render routes: TemplateExpressionError and RenderExecutionError now return 422 with code

POST /render and POST /render/html previously returned an opaque 500 when a template contained an invalid Handlebars expression (TemplateExpressionError) or the PDF engine timed out or crashed (RenderExecutionError). These are now intercepted in-route and returned as classified 422 responses, matching the behavior already in place for the preview routes.

New 422 responses on /render and /render/html:

ShapeWhen
{ "error": "Validation Failed", "issues": [...] }Data does not satisfy the template’s inputSchemapreserved, no change
{ "error": "RenderError", "code": "template_expression_error", "message": "..." }Template has an invalid Handlebars expression
{ "error": "RenderError", "code": "render_timeout" | "engine_crash", "message": "..." }PDF engine timed out or crashed (PDF route only)

The existing { error: 'Validation Failed', issues: [...] } path for RenderValidationError is preserved — callers that already handle this shape are unaffected.

The OpenAPI spec now declares a 422 response on both routes as an anyOf union covering both shapes.

2. /render/validate — sharper contract, retired RENDER_ERROR code

The /render/validate render-check step previously returned all errors under the single RENDER_ERROR code, conflating user-caused template/data problems with unexpected server failures.

Breaking change: RENDER_ERROR is retired. The new codes are:

issues[].codeStepMeaning
INVALID_TEMPLATE1 — structuralZod schema validation failure. path indicates the failing field. Unchanged.
validation_failed2 — render checkData does not satisfy the template’s inputSchema.
template_expression_error2 — render checkTemplate contains an invalid Handlebars expression.

Unexpected server failures during the render check now surface as 500 rather than 200 { valid: false, issues: [RENDER_ERROR] }. This correctly separates infrastructure faults from user validation problems — callers no longer need to debug their payload in response to a server error.

3. /render/validate issue codes formally declared in OpenAPI

ValidationResultSchema.issues[].code is now a closed TypeBox union (INVALID_TEMPLATE | validation_failed | template_expression_error) rather than a free string. The generated OpenAPI spec at /docs/json now explicitly enumerates the allowed codes, making the contract machine-readable for API consumers and documentation generators.


Validation

  • pnpm typecheck — 10/10 passed
  • pnpm lint — 0 errors (1 pre-existing unrelated warning)
  • pnpm --filter @pulp-engine/api test — 582 passed, 41 skipped, 0 failed

Upgrade

/render and /render/html: No breaking changes. The RenderValidationError 422 shape is preserved. TemplateExpressionError and RenderExecutionError change from 500422 with a code — this is strictly an improvement.

/render/validate: The RENDER_ERROR issue code is removed. Callers checking for code === 'RENDER_ERROR' must update to handle validation_failed and template_expression_error. Callers that do not inspect the code field are unaffected. Unexpected server failures now return 500 instead of 200 { valid: false } — callers must handle 500 as a server-side fault (not a validation issue).

No migrations, no credential changes, no new environment variables.

docker pull ghcr.io/OWNER/pulp-engine:v0.41.0