← Back to list

From “Library Not Found” to Lambda Hero: A Deep Dive into Zbar, Poppler, and Shared Libraries

You have an idea. A brilliant, simple idea: an AWS Lambda function, written in Python, that automatically processes uploaded PDFs. It needs…

Dinesh V · 2025-06-30 15:18 · 0 claps · 3.6 min read
#aws-lambda-layer #python #pyzbar #poppler #aws-lambda
Open on Medium ↗
Wiki topics: ☁️ · DevOps & Cloud 📚 · Books & Reading

From “Library Not Found” to Lambda Hero: A Deep Dive into Zbar, Poppler, and Shared Libraries

You have an idea. A brilliant, simple idea: an AWS Lambda function, written in Python, that automatically processes uploaded PDFs. It needs to read QR codes and maybe some text. You grab some great libraries like pyzbar for the QR codes and pdf2image to handle the PDFs. It all works flawlessly on your local machine.

You package it, deploy it to Lambda, and trigger it with a test file. And then…

[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': Unable to find zbar shared library

If you’ve seen this error, or its equally frustrating cousin, PDFInfoNotInstalledError: Is poppler installed and in PATH?, then this post is for you. You are about to embark on a journey into the world of C shared libraries, linker paths, and Docker builds. Don't worry, I've already made the trip, and I’ve drawn a map so you don’t get lost.

The Core Problem: Python Wrappers and Their Hidden Needs

The first thing to understand is that libraries like pyzbar and pdf2image are not pure Python. They are brilliant Python "wrappers" around powerful, high-performance programs written in C/C++.

  • pyzbar is a wrapper for the zbar C library. It needs a file called libzbar.so.
  • pdf2image is a wrapper for the poppler utility suite. It needs executable programs like pdfinfo and pdftoppm.

The AWS Lambda environment is a minimal, stripped-down version of Linux. It does not come with these C libraries and programs pre-installed. When your Python code says import pyzbar, the system looks for libzbar.so and, finding nothing, crashes.

To fix this, we need to package all these hidden dependencies into a Lambda Layer.

The Two Paths You Must Know: PATH vs. LD_LIBRARY_PATH

This is the single most important concept. In Linux:

  • **PATH is an environment variable that tells the system where to look for executable programs** (like pdfinfo).
  • **LD_LIBRARY_PATH is an environment variable that tells the system where to look for shared libraries** (.so files) that executables depend on.

Our solution needs to satisfy both.

The Ultimate Solution: Building a Complete Layer with Docker

We can’t just pip install these dependencies. We need to build them in an environment that perfectly matches our Lambda runtime (Amazon Linux 2, x86_64 architecture). Docker is the perfect tool for this.

Here is the final, battle-hardened build script that will create a layer containing everything you need.

1. Your Project Setup

Create a directory on your machine with two files:

**requirements.txt**

Plaintext

pyzbar
pdf2image
Pillow
boto3

**build_layer.sh** (The star of our show)


#!/bin/bash
#Stop on any error 
set -e
LAYER_NAME="lambda_complete_layer"
echo "Cleaning up previous build artifacts..."
rm -rf ./build
mkdir -p ./build
echo "Building final layer: Compiling Zbar and packaging Poppler with all dependencies..."
docker run \
    --platform linux/amd64 \
    -v "$PWD":/var/task \
    public.ecr.aws/sam/build-python3.9 \
    /bin/bash -c '
        # 1. Enable the EPEL repository to get access to the zbar package
        amazon-linux-extras install -y epel
        # 2. Install all system-level dependencies
        yum install -y \
            zbar \
            poppler-utils \
            gcc make autoconf automake libtool pkgconfig libpng-devel zip
        # 3. Compile Zbar from source (The most reliable method we found)
        echo "Downloading and compiling zbar from source..."
        cd /tmp
        curl -L -o zbar.tar.bz2 "https://sourceforge.net/projects/zbar/files/zbar/0.10/zbar-0.10.tar.bz2/download"
        tar -xjf zbar.tar.bz2
        cd zbar-0.10
        ./configure --disable-video --without-imagemagick --without-gtk --without-qt --without-python --without-x
        make && make install DESTDIR=/tmp/zbar_compiled

        # 4. Create the required directory structure for the layer
        mkdir -p /var/task/build/python/lib/python3.9/site-packages
        mkdir -p /var/task/build/lib
        mkdir -p /var/task/build/bin
        # 5. Install Python packages
        pip install -r /var/task/requirements.txt -t /var/task/build/python/lib/python3.9/site-packages
        # 6. Copy our compiled zbar libs and poppler executables
        echo "Copying executables and zbar libraries..."
        cp /usr/bin/pdfinfo /usr/bin/pdftoppm /usr/bin/pdftocairo /var/task/build/bin/
        cp -L /tmp/zbar_compiled/usr/local/lib/libzbar.so* /var/task/build/lib/

        # 7. The Masterstroke: Find and copy ALL Poppler dependencies at once using ldd
        echo "Finding all shared library dependencies for Poppler tools via ldd..."
        ALL_DEPS=$(ldd /usr/bin/pdfinfo /usr/bin/pdftoppm | grep "=> /" | awk "{print \$3}" | sort -u)
        echo "Copying all discovered dependencies: $ALL_DEPS"
        for dep in $ALL_DEPS; do
            cp -L "$dep" "/var/task/build/lib/"
        done

        # 8. Create the final zip file
        cd /var/task/build
        zip -r9 ../'${LAYER_NAME}'.zip .
    '
echo "Build complete! Your layer is ready in ${LAYER_NAME}.zip"

Run this script with ./build_layer.sh. It will produce a lambda_complete_layer.zip file.

The Final Step: Configuring Your Lambda Function

After you upload the .zip file as a new Lambda Layer and attach it to your function, you must configure the environment variables. This is the step that tells Lambda how to use the layer.

  • Go to your Lambda function’s Configuration -> Environment variables.
  • Add the following two variables:

Key Value

LD_LIBRARY_PATH = /opt/lib

PATH = /opt/bin

And that’s it. The LD_LIBRARY_PATH tells the system where to find libzbar.so and all of Poppler's .so dependencies. The PATH tells the system where to find the pdfinfo program itself.

Lessons Learned from the Trenches

  • “File not found” is a PATH problem, not a permissions problem. Don’t reach for chmod 777.
  • A library’s dependencies have their own dependencies. The reason we had to keep adding libraries (liblcms2, libopenjpeg) is that they were dependencies of Poppler's libraries.
  • Use ldd to end the madness. The ldd command is your best friend for uncovering the entire dependency chain of an executable. It stops the frustrating cycle of deploying, failing, and adding one library at a time.
  • When in doubt, compile from source. When package managers fail or have inconsistent versions (as we saw with zbar), compiling from source gives you full control.

This journey through dependency hell was tough, but the result is a robust, self-contained deployment that will work every time. Hopefully, this map saves you from getting lost on your own adventure.

Happy coding!


메타데이터
post_id
4d7ca3e3d3f9
slug
from-library-not-found-to-lambda-hero-a-deep-dive-into-zbar-poppler-and-shared-libraries-4d7ca3e3d3f9
url
https://medium.com/@svallamsetti/from-library-not-found-to-lambda-hero-a-deep-dive-into-zbar-poppler-and-shared-libraries-4d7ca3e3d3f9
canonical_url
https://medium.com/@svallamsetti/from-library-not-found-to-lambda-hero-a-deep-dive-into-zbar-poppler-and-shared-libraries-4d7ca3e3d3f9
author_url
https://medium.com/@svallamsetti
status
ok
fetched_at
2026-07-19 05:28:52