PDFPipe

Serverless functions / AWS Lambda

WeasyPrint on AWS Lambda: the libraries pip cannot install

"OSError: cannot load library 'libgobject-2.0-0': libgobject-2.0-0: cannot open shared object file", raised on import rather than on render.

What is actually wrong

WeasyPrint is Python but its text and graphics work is done by Pango, Cairo, HarfBuzz and GLib, which are C libraries loaded through cffi at import time. pip installs Python packages; it does not install C libraries, and no wheel bundles these. On a development machine they are already present because something else installed them, which is why this failure only ever appears on the first deploy.

What AWS Lambda gives you to work with

a function that is handed a request, runs, and is frozen again. The execution environment is reused between invocations but you do not control when it is torn down.

  • Packaging: 250 MB unzipped for the function code and every layer attached to it, combined. That is the hard number most PDF deployments run into. A container image raises it to 10 GB but changes how the function is built and pushed.
  • Filesystem: the deployment package is read-only. Only /tmp is writable, and it defaults to 512 MB. Anything the process writes there survives for the life of the execution environment, not the invocation, which is a subtle source of both caching wins and stale-state bugs.
  • Processes: a child process can be spawned and it lives while the invocation does. When the invocation returns, the environment is frozen mid-execution rather than terminated, so a process that has not exited is simply suspended and resumed on the next call.

The fix, if you are keeping WeasyPrint

Build a layer from the Lambda base image containing the shared libraries and their dependencies, then set the linker and library discovery variables the loader needs. Fonts go in the same layer for the same reason as wkhtmltopdf.

bash
# Built FROM the matching Lambda Python base image.
#   dnf install -y pango cairo gdk-pixbuf2 libffi
# Copy the resolved .so files into the layer at /opt/lib, then set:
#   LD_LIBRARY_PATH=/opt/lib
#   GI_TYPELIB_PATH=/opt/lib/girepository-1.0
#   XDG_DATA_DIRS=/opt/share
#   FONTCONFIG_PATH=/opt/fonts

What still hurts after that

The layer is tied to the base image it was built on and has to be rebuilt when the runtime moves. More importantly, this is the only entry on this list where the workaround changes what the document can contain: WeasyPrint does not execute JavaScript, so anything drawn by a client-side chart library arrives as an empty container. If the document was designed in a browser, some of it will not survive the move, and that is a content decision rather than an infrastructure one.

What WeasyPrint is genuinely good at

it implements the parts of the paged media specification that browser engines never did, including running headers and footers in page margin boxes, and it uses a fraction of the memory a browser does. That is worth keeping in view: the problem on this page is where it runs, not what it produces. WeasyPrint is a Python library that implements CSS Paged Media directly, without a browser, on top of the Pango and Cairo text and graphics stack. It needs Pango, Cairo, HarfBuzz, GDK-PixBuf and GLib as system shared libraries. These are not Python packages and no wheel contains them.

The other shape of the answer

Every fix above keeps the renderer inside your deployment, which means the constraint stays yours: the package size, the shared libraries, the fonts, the memory, the patching. The alternative is an HTTP call from AWS Lambda to something that already has a browser in it, which turns all of the above into a request and a response. That is what this API is, and it is the reason these pages exist. Whether that trade is right depends on whether rendering is a thing you want to operate.

Frequently asked

Can WeasyPrint run on AWS Lambda at all?

Build a layer from the Lambda base image containing the shared libraries and their dependencies, then set the linker and library discovery variables the loader needs. Fonts go in the same layer for the same reason as wkhtmltopdf. Whether that is worth doing is a separate question from whether it is possible, and the section above on what still hurts is the honest answer to it.

Why does it work locally?

Because a development machine has root, a package manager, several gigabytes of memory, a full font set and no packaging limit. Every one of those is a thing AWS Lambda constrains. A renderer that works locally and fails on deploy has not regressed: it has met the first environment that does not give it everything.

Related failures

The same platform with a different renderer, and the same renderer on other platforms.

Puppeteer on AWS Lambda: the 250 MB package limit

The deploy fails before the function ever runs, with an error naming the unzipped size of the code and layers.

Playwright on AWS Lambda: browsers that are not in your bundle

At runtime, not at deploy time: "Executable doesn't exist at /home/sbx_user1051/.cache/ms-playwright/chromium-.../chrome-linux/chrome".

wkhtmltopdf on AWS Lambda: a binary with no libraries to link against

"error while loading shared libraries: libXrender.so.1: cannot open shared object file", or the process exits with no output and no error at all.

WeasyPrint on Google Cloud Run: a small image that renders differently

The deploy is easy, the memory footprint is a tenth of a browser's, and the documents come out subtly wrong: a chart is missing, a web font fell back, a flex layout collapsed.

WeasyPrint on Azure Functions: GLib is not a pip package

The function app deploys and every invocation fails on import with "cannot load library 'libgobject-2.0-0'".

WeasyPrint on Docker: a Pango version that does not match

It installs and runs, and the text is subtly wrong: incorrect kerning, broken ligatures, or an exception about a symbol that is not found in a shared library.

WeasyPrint on Heroku: an Aptfile and a library path

Deployment succeeds and the app crashes on boot with "cannot load library 'libpango-1.0-0'".

Every renderer, on every platform

The full grid, grouped by what kind of environment the platform is.

What goes wrong when HTML becomes a PDF

Once it deploys, the next set of problems is in the output rather than the infrastructure.

If the render moves off this platform, none of the above is your problem to keep solving. 100 free documents a month, and a playground that needs no signup.