ayushb.comDamak, Jhapa · NepalAvailable for consultingAvailable
← All posts

Blog · 29 October 2026 · 17 min read

Keeping my Canon PIXMA G2010 printing and scanning on modern macOS

I kept my Canon PIXMA G2010 printing and scanning on current macOS with Gutenprint and SANE. These are my findings and the steps I used.

I have a Canon PIXMA G2010 that still prints. Canon does not ship a macOS driver for it, and its compatibility list marks the printer as not supported from macOS 14 onward. I did not want to replace a working printer because the vendor dropped support, so I set out to make it print and scan on a current Mac.

It prints through Gutenprint 5.3.4, which has a definition for the G3010 (same print engine), and scans through SANE’s pixma backend. The setup needs Terminal, a source build, and an admin password. I tested it on macOS 27.0.1 (26A434, arm64), CUPS 2.3.4, with one G2010 over USB. Nothing here is supported by Canon or Apple.

The short version: the setup fails if you install Gutenprint under /usr/local. macOS runs print filters in a sandbox that only allows reads from its own directories and /Library/Printers. Gutenprint cannot read its printer database there, so it crashes. CUPS reports the crash as Filter failed, and the error log shows nothing useful.

This post is both: the findings that took the most time, and the steps I used. If you only want the steps, start at Before you start.

No official driver

I checked Canon’s macOS compatibility list for inkjet printers and scanners, updated 2026-01-23. It says:

Model macOS 14 macOS 15 macOS 26
PIXMA G2010 Not Supported Not Supported Not Supported
PIXMA G3010 Not Supported Not Supported Not Supported
PIXMA G2000 CUPS driver CUPS driver CUPS driver

The G2000 driver is for different hardware. It has a different print head and different inks despite the similar name, and it stops at macOS 10.15.

Canon never published a Mac driver for the G2010 in any region. Its support page has Windows downloads only.

That left a third-party driver.

What I found

Four things took most of the time:

  • The install location. A build under /usr/local looks correct. Then every job fails. The cupsd sandbox blocks the filter from reading Gutenprint’s printer database. Details
  • The build. Gutenprint 5.3.4 needs four fixes on current macOS. Details
  • The PPD. The filter path must be absolute, and the *NickName must keep the full version. Details
  • The model. Gutenprint has no G2010 entry. The G3010 definition printed correctly on my unit. Details

The rest of this post explains each one. If you want the steps without the story, start at Before you start.

What the printer reports

Before I built anything, I looked at what the Mac saw. lpinfo -v showed a line like this:

direct usb://Canon/G2010%20series?serial=<SERIAL>

The USB backend reports the device as:

direct usb://Canon/G2010%20series?serial=<SERIAL> "Canon G2010 series" \
  "Canon G2010 series" \
  "MFG:Canon;MDL:G2010 series;CMD:BJRaster3,IVEC;CLS:PRINTER;\
DES:Canon G2010 series;VER:1.060;STA:10;PSE:KNMG02784;CID:CA_BJR520_IJP;"

The USB IDs are 04a9:183a. The device has two interfaces:

  • Interface class 7 (printer), subclass 1, protocol 2: bi-directional printing.
  • Interface class 255 (vendor-specific), subclass 0, protocol 255, three endpoints: Canon’s scan and status channel.

CMD:BJRaster3 is the token that matters. The printer uses Canon’s BJ Raster 3 format, which Gutenprint’s Canon backend produces.

The printer is an all-in-one: it prints, scans on a flatbed, and copies. I needed both halves: Gutenprint for printing and SANE for scanning.

The failure that sent me to the log

My first build used the usual ./configure --prefix=/usr/local. The queue, the PPD, and the filter all looked correct.

On current macOS, cupsd runs print filters in a sandbox. A filter can read its own code, the CUPS spool, and vendor directories under /Library/Printers. It cannot read arbitrary paths such as /usr/local.

The setup looked correct:

  • lpstat shows the queue.
  • The PPD is installed.
  • The filter binary runs when you invoke it by hand.
  • The backend talks to the printer.

Every job then fails with:

printer Canon_G2010 is idle.
    Filter failed

/var/log/cups/error_log showed only USB back-channel chatter. The filter’s own messages never appeared. I expected the filter to be broken.

The unified log shows the cause:

kernel: (Sandbox) Sandbox: rastertogutenprint.5.3(20179) deny(1)
  file-read-metadata /usr/local/share/gutenprint/5.3/xml/printers/dyesub.xml
kernel: (Sandbox) Sandbox: rastertogutenprint.5.3(20179) deny(1)
  file-read-metadata /usr/local/share/gutenprint/5.3/xml/printers/raw.xml

The filter could not read Gutenprint’s printer database. It started with an empty printer list and crashed:

ls /Library/Logs/DiagnosticReports/ | grep rastertogutenprint
rastertogutenprint.5.3-2026-10-29-093401.ips
rastertogutenprint.5.3-2026-10-29-093507.ips
exception: EXC_BAD_ACCESS (SIGSEGV) at 0x0000000000000000
faulting thread frames:
  _platform_strcmp
  stpi_find_duplicate_printers
  stp_module_init
  stp_init
  main

I read src/main/printers.c after the crash. Gutenprint 5.3.4’s stpi_find_duplicate_printers() does this:

size_t nelts = stp_list_get_length(printer_list);
const char **str_data = stp_zalloc(sizeof(const char *) * nelts);
/* ... */
for (i = 0; i < nelts - 1; i++)   /* nelts == 0 makes nelts - 1 wrap to SIZE_MAX, so the loop runs off the array */

With an empty list, nelts - 1 underflows and the loop reads past the end of str_data until strcmp dereferences NULL.

The comparator is also wrong. It compares n2 with itself instead of n1 with n2, but that bug is not the cause of this crash.

What I took from it:

  1. Filter failed with a clean error_log points to the sandbox, not the filter.
  2. I test the filter directly with a raster on stdin. If it works there and fails under cupsd, the sandbox is the difference.
  3. I install CUPS drivers under /Library/Printers, as vendor packages do. --prefix=/usr/local is the wrong default on macOS.
  4. The crash report in /Library/Logs/DiagnosticReports named the process that crashed.

The same applies to other CUPS drivers installed outside /Library/Printers.

The build needed four fixes

Gutenprint 5.3.4 did not build or install cleanly on current macOS. I hit four problems, and the Step 5 command works around all of them.

The u_int error

Gutenprint compiles with -D_POSIX_C_SOURCE=200809L -std=c99. Under that feature set, the macOS SDK hides u_int. CUPS headers include <netinet/ip.h>, which uses u_int, so the build stops:

/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/netinet/ip.h:86:2:
  error: unknown type name 'u_int'

The fix is to enable Darwin extensions:

CPPFLAGS="-D_DARWIN_C_SOURCE"

The --with-cups-config flag

Passing --with-cups-config=/path/to/cups-config sets CUPS_CONFIG but never sets FOUND_CUPS_CONFIG. Configure then stops:

configure: error: You do not have the necessary software installed to build the CUPS driver.

Do not use the flag. Put a wrapper named cups-config first in PATH. The normal detection path finds it.

The read-only system volume

Gutenprint installs PPDs and calibrate.ppm into the CUPS data directory reported by cups-config --datadir. On macOS that is /usr/share/cups, part of the sealed system volume:

install: /usr/share/cups/model/gutenprint/5.3//INS@...: No such file or directory
install: /usr/share/cups/INS@...: Operation not permitted
make[4]: *** [install-pkgdataDATA] Error 71

The shim in Step 4 redirects --datadir and --serverbin under the install prefix.

Root-owned files in the build tree

make install runs cups-genppd as root and leaves root-owned ppd/ files in the build directory. The next make as your normal user fails with Permission denied on ppd-clean.

Run sudo chown -R "$(id -u):$(id -g)" . on the tree and try again.

None of these appeared in one place. I found them by reading the errors and the build files, and the guide’s Step 5 applies all four fixes.

The PPD had two requirements

The PPD looked fine at first. It was not.

The filter path must be absolute

Gutenprint’s generated PPD says:

*cupsFilter: "application/vnd.cups-raster 100 rastertogutenprint.5.3"

A bare filter name is resolved in /usr/libexec/cups/filter, which is part of the read-only system volume. You cannot put a third-party filter there. I changed the PPD to point at the real binary:

*cupsFilter: "application/vnd.cups-raster 100 /Library/Printers/Gutenprint/libexec/cups/filter/rastertogutenprint.5.3"

The *NickName carries the version

I renamed the PPD for the G2010, but the version had to stay full:

*NickName: "Canon PIXMA G2010 - CUPS+Gutenprint v5.3.4-2022-06-24T01-00-8808d602"

When I shortened it to ... CUPS+Gutenprint v5.3.4, the filter refused to run:

ERROR: The PPD version (5.3.4) is not compatible with Gutenprint 5.3.4-2022-06-24T01-00-8808d602.
ERROR: Please run `/usr/local/sbin/cups-genppdupdate' as administrator.

The filter parses the version from the nickname and compares it with the string compiled into the library. The git snapshot has a long string. A release tarball uses a shorter string, so its nickname and library match without this edit.

The G3010 definition printed correctly

Gutenprint 5.3.4 has no G2010 entry. I needed a definition that matched the print engine. The closest was bjc-PIXMA-G3010, with internal model id 17001000.

The G2010 and G3010 share the same 4-ink GI-190 print engine. The G3010 adds a scanner. The G3010 definition printed correct pages on a G2010 in my test, including alignment and margins, for plain text and a colour test sheet.

I inferred this from the model family and tested it on one unit. Canon and Gutenprint do not document it.

Before you start

If you want to reproduce this, here is the path I took. It is not a normal Mac install. You will use Terminal, build a driver from source, and type an admin password. A macOS update can break the queue, and you may need to repeat the build.

The G2010 is not an official Gutenprint model. The G3010 definition is a workaround, tested on one unit.

If you are not comfortable with that, use one of the alternatives at the end.

You need:

  • A Mac running macOS 14 or later. I tested macOS 27.0.1.
  • A PIXMA G2010 connected by USB. A direct port is best. A hub may work.
  • An admin account on the Mac.
  • Xcode Command Line Tools.
  • Homebrew.
  • About 30 minutes.

Open Terminal from Applications > Utilities. Copy each command block into Terminal and press Return after it.

The commands assume you build in ~/canon-g2010. Adjust the paths if you use another directory.

sudo runs one command as an administrator. It asks for your password.

The steps use the fixes from the findings above.

Step 1: Check the printer connection

Run:

lpinfo -v

Look for a line like this:

direct usb://Canon/G2010%20series?serial=<SERIAL>

Copy the whole usb://... value. You need it in Step 7. Keep the %20 in G2010%20series. It is a URL-encoded space.

If you do not see the printer, check the cable and the USB port. This command should also show it:

system_profiler SPUSBDataType | grep -A 5 -i canon

Step 2: Install the tools

Install Xcode Command Line Tools:

xcode-select --install

A dialog opens. Install the tools and wait for it to finish.

Check whether Homebrew is installed:

brew --version

If it is not installed, run the Homebrew installer:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

The installer prints two commands to add Homebrew to your shell. Run them, then open a new Terminal window.

Install SANE for scanning:

brew install sane-backends

This also installs scanimage, which Step 9 uses.

Step 3: Download Gutenprint

Create a working directory and download the 5.3.4 source:

mkdir -p ~/canon-g2010
cd ~/canon-g2010
curl -LO https://archive.ubuntu.com/ubuntu/pool/main/g/gutenprint/gutenprint_5.3.4.20220624T01008808d602.orig.tar.xz
tar xf gutenprint_5.3.4.20220624T01008808d602.orig.tar.xz
cd gutenprint-5.3.4-2022-06-24T01-00-8808d602

The Ubuntu archive carries the 5.3.4 git snapshot as an orig tarball. The SourceForge download endpoint returns an HTML challenge page from some networks.

If curl fails, open the URL in a browser, download the file, and move it into ~/canon-g2010.

Step 4: Create the cups-config shim

The build needs a wrapper around the system cups-config. The wrapper redirects two paths into the install prefix. Without it, the install tries to write to /usr/share/cups, which is part of the read-only system volume.

Create the wrapper:

mkdir -p ../shimbin
cat > ../shimbin/cups-config <<'EOF'
#!/bin/sh
prefix=${GP_PREFIX:-/usr/local}
for arg in "$@"; do
  case "$arg" in
    --datadir)   echo "$prefix/share/cups";   exit 0 ;;
    --serverbin) echo "$prefix/libexec/cups"; exit 0 ;;
  esac
done
exec /usr/bin/cups-config "$@"
EOF
chmod +x ../shimbin/cups-config

Step 5: Configure, build, and install

Run these commands from the Gutenprint source directory:

GP_PREFIX=/Library/Printers/Gutenprint \
PATH="$PWD/../shimbin:$PATH" \
./configure \
  --prefix=/Library/Printers/Gutenprint \
  --disable-nls \
  --enable-cups-ppds \
  --disable-translated-cups-ppds \
  --disable-samples \
  --disable-test \
  CPPFLAGS="-D_DARWIN_C_SOURCE"

Then build and install:

make -j8
sudo make install

sudo asks for your admin password. The install writes only under /Library/Printers/Gutenprint.

The build takes a few minutes. If make fails because root-owned files are left in the source tree after a previous install, fix the ownership and run it again:

sudo chown -R "$(id -u):$(id -g)" .

Step 6: Patch the PPD

The PPD is the printer description file. Unpack the G3010 definition:

gunzip -c /Library/Printers/Gutenprint/share/cups/model/gutenprint/5.3/C/stp-bjc-PIXMA-G3010.5.3.ppd.gz > Canon-PIXMA-G2010.ppd

Set the display name, the driver name, and the filter path:

sed -i '' \
  -e 's|^\*ShortNickName:.*|*ShortNickName: "Canon PIXMA G2010"|' \
  -e 's|^\*NickName:.*|*NickName: "Canon PIXMA G2010 - CUPS+Gutenprint v5.3.4-2022-06-24T01-00-8808d602"|' \
  -e 's|^\*cupsFilter:.*|*cupsFilter: "application/vnd.cups-raster 100 /Library/Printers/Gutenprint/libexec/cups/filter/rastertogutenprint.5.3"|' \
  Canon-PIXMA-G2010.ppd

Check the result:

grep -E '^\*(ShortNickName|NickName|cupsFilter):' Canon-PIXMA-G2010.ppd

You should see the full version string in *NickName and the absolute path in *cupsFilter. The *ShortNickName is optional. lpadmin -D sets the name macOS shows for the queue.

Do not shorten the version. The filter compares it with the version compiled into the library.

Step 7: Create the print queue

Replace YOUR_SERIAL with the serial from Step 1. Keep the single quotes around the URI.

lpadmin -p Canon_G2010 -E \
  -v 'usb://Canon/G2010%20series?serial=YOUR_SERIAL' \
  -P "$PWD/Canon-PIXMA-G2010.ppd" \
  -D "Canon PIXMA G2010" -L "USB"

lpadmin -p Canon_G2010 -o PageSize=A4
lpadmin -d Canon_G2010

lpadmin -d makes the printer the system default. It is optional.

Check the queue:

lpstat -p Canon_G2010

macOS prints a warning that printer drivers are deprecated. That is expected. See Limitations.

Step 8: Print a test page

Print a PDF from any app, or use the command line. Save a document as a PDF to your Desktop, then run:

lp -d Canon_G2010 ~/Desktop/test.pdf
lpstat -p Canon_G2010
lpstat -o Canon_G2010

The job should complete and the printer should return to idle.

If the job fails, go to If something goes wrong.

Step 9: Set up scanning

Find the scanner:

scanimage -L

You should see a line like this:

device `pixma:04A9183A_<SERIAL>' is a CANON Canon PIXMA G2010 Series multi-function peripheral

Use the full device name from that line:

scanimage -d 'pixma:04A9183A_<SERIAL>' \
  --format=png --mode Color --resolution 300 --source Flatbed > scan.png
open scan.png

The scanner and the printer use different USB interfaces. You can print and scan at the same time.

If something goes wrong

Filter failed and an empty error log

This is usually a sandbox problem, not a broken filter. I explain why in The failure that sent me to the log.

Check the unified log:

/usr/bin/log show --last 10m --predicate 'eventMessage CONTAINS[c] "gutenprint"'

Sandbox denials look like this:

kernel: (Sandbox) Sandbox: rastertogutenprint.5.3(20179) deny(1)
  file-read-metadata /usr/local/share/gutenprint/5.3/xml/printers/dyesub.xml

Use /usr/bin/log, not log. In zsh, log is a builtin.

Rebuild with /Library/Printers/Gutenprint as the prefix. Do not use --prefix=/usr/local.

The build stops with unknown type name 'u_int'

Add CPPFLAGS="-D_DARWIN_C_SOURCE" to the configure command in Step 5.

Configure says it cannot find CUPS

Do not pass --with-cups-config. Use the cups-config shim from Step 4 and put its directory first in PATH, as the Step 5 command does.

make install fails with Operation not permitted

The shim is not redirecting the install paths. Check that GP_PREFIX is set and that the shim is executable.

A later make fails with Permission denied

The previous make install left root-owned files in the source tree. Run:

sudo chown -R "$(id -u):$(id -g)" .

The filter says the PPD version is not compatible

Restore the full version string in *NickName:

ERROR: The PPD version (5.3.4) is not compatible with Gutenprint 5.3.4-2022-06-24T01-00-8808d602.

The filter reads the version from the nickname and compares it with the library. Keep the full v5.3.4-2022-06-24T01-00-8808d602 suffix.

The filter works alone but the queue fails

Test the filter without CUPS. Use a PDF you can print:

cupsfilter -p /etc/cups/ppd/Canon_G2010.ppd -m application/vnd.cups-raster page.pdf > page.raster

Run the filter directly:

DEVICE_URI='usb://Canon/G2010%20series?serial=YOUR_SERIAL' \
PPD=/etc/cups/ppd/Canon_G2010.ppd \
  /Library/Printers/Gutenprint/libexec/cups/filter/rastertogutenprint.5.3 \
  1 "$USER" test 1 '' < page.raster > /dev/null

If this works and the queue still says Filter failed, the problem is the sandbox or a path, not the driver.

Crash reports

Check for a recent crash:

ls /Library/Logs/DiagnosticReports/ | grep rastertogutenprint

A crash report means the filter process died. The report names the process and the failing frame.

Scanning notes

Scanning was easier than printing. SANE’s pixma backend lists the G2010 and works over USB. Gutenprint handles printing only. Canon’s Image Capture scanner driver does not exist for this model on modern macOS, so Image Capture and Preview do not see the scanner.

Notes from my run:

  • At 150 dpi, an A4 colour scan is 1276×1754 px, about 3.2 MB, and takes about 14 seconds.
  • The backend offers 75, 150, 300, and 600 dpi.
  • The modes are Color, Gray, and Lineart.
  • Printing and scanning use different USB interfaces, so they can run at the same time.
  • sane-find-scanner may list unrelated USB devices, such as a USB Ethernet adapter, as “possible scanners”. Ignore them.

Verification

  • I watched lpstat -p return the job to idle with no new crash reports.
  • I printed a text page. The full character set, rules, and box drawing aligned correctly.
  • I printed a colour test page with 8 primary and secondary bars, an RGB sweep, a greyscale ramp, and mixed tones from a generated PDF.
  • I scanned a real document at 150 dpi. It was legible and had correct A4 geometry.

What I did not test: long-term stability, sleep/wake and replug behaviour, print quality against a Canon reference, other macOS versions, or other units.

Limitations

  • PPD drivers are being retired. CUPS 2.3.4 warns that printer drivers are deprecated and will stop working in a future version. CUPS 3.x is driverless. This setup depends on CUPS 2.x, so I expect a few years, not a decade.
  • Gutenprint marks G-series support as experimental. Plain paper and graphics are fine. Photo colour may not match Canon’s output.
  • Canon and Gutenprint do not validate the G3010 substitution. It is the same engine family, but I tested one unit.
  • No scanner integration with macOS apps. I use SANE only (scanimage, xsane). Image Capture and Preview do not see the scanner.
  • The driver installs as root. It installs into /Library/Printers, the normal place for vendor filters, but it is a locally built binary.
  • A macOS update can invalidate the queue. I will re-check after major upgrades.

Uninstall

Remove the queue and the driver:

lpadmin -x Canon_G2010
sudo rm -rf /Library/Printers/Gutenprint
brew uninstall sane-backends

The last command is only needed if you no longer want scanning.

This procedure writes nothing to /usr/local. If you tried an earlier --prefix=/usr/local build, remove those Gutenprint files too. They will not work under the sandbox.

Alternatives

If I were setting this up for several Macs, I would use a network print server. A Raspberry Pi running CUPS and Gutenprint on Linux can expose the printer as a network queue. macOS can add it without a local driver. This is more reliable for several Macs, but it needs another computer.

If I wanted a supported setup, I would look at PrintFab. It lists the G2010 and does its own rasterization. It costs money and is closed source, but the vendor supports it.

If I only needed the printer now and then, I would keep an old Mac or Windows PC for it. You need another machine, but no setup on the Mac.

Tested with

Item Detail
macOS 27.0.1 (26A434), arm64
CUPS 2.3.4
Gutenprint 5.3.4-2022-06-24T01-00-8808d602 (source build)
SANE sane-backends 1.4.0 (Homebrew)
Device PIXMA G2010, USB 04a9:183a, CMD:BJRaster3,IVEC
Printer URI usb://Canon/G2010%20series?serial=<SERIAL>

The serial is redacted. Use lpinfo -v to find yours.