pdftopdf (cfFilterPDFToPDF) no longer generates soft copies with *cupsManualCopies: True — regression in libcupsfilters 2.2.x
Summary
After upgrading libcupsfilters 2.1.1 → 2.2.1, printing with copies > 1 to a raster-driver
queue produces exactly one copy. The queue uses a classic CUPS raster driver
(*cupsFilter: "application/vnd.cups-raster 0 rastertosnailtspl-xprinter") whose PPD has
*cupsManualCopies: True, so the copies must be produced in software by
pdftopdf / cfFilterPDFToPDF().
pdftopdf runs and exits with status 0, but the page count is not multiplied: Ghostscript is
subsequently invoked without any copy count (no /NumCopies), and only a single copy reaches
the printer.
Nothing else changed on the system: the same queue, same PPD and same vendor filter worked
correctly with libcupsfilters 2.1.1. Downgrading libcupsfilters back to 2.1.1 is the only change
needed to restore correct behaviour.
libcupsfilters 2.2.0 rewrote cfFilterPDFToPDF() from C++/QPDF to C/PDFio, which appears to be
where the regression was introduced:
https://openprinting.github.io/libcupsfilters-2.2.0
Environment
| Item |
Value |
| Distribution |
CachyOS (Arch Linux based), x86_64 |
| cups |
2:2.4.19-1 |
| cups-filters |
2.0.1-2.1 |
| libppd |
2.1.1-2.1 |
| libcupsfilters |
2.2.1-2.1 (broken) / 2.1.1-4.4 (works) |
| Printer |
Xprinter XP-420B (203 dpi thermal label printer, USB) |
| Driver |
xprinter-cups 3.13.55-2 (vendor CUPS raster filter rastertosnailtspl-xprinter) |
| Ghostscript |
in filter chain via cfFilterGhostscript |
Relevant PPD lines:
*cupsManualCopies: True
*cupsFilter: "application/vnd.cups-raster 0 rastertosnailtspl-xprinter"
Exact upgrade timestamp from /var/log/pacman.log:
[2026-08-31T10:48:08+0300] [ALPM] upgraded libcupsfilters (2.1.1-4.4 -> 2.2.1-2.1)
The breakage was noticed the same day.
Steps to reproduce
-
Set up a CUPS queue with a classic raster driver whose PPD contains
*cupsManualCopies: True and a single *cupsFilter: "application/vnd.cups-raster 0 <vendor filter>".
-
Submit a job with more than one copy, e.g.:
lp -d Xprinter_XP-420B -n 3 /usr/share/cups/data/testprint.ps
-
Observe the output.
Expected behaviour
Three copies are printed. Because the printer cannot generate copies in hardware and
*cupsManualCopies: True is set, cfFilterPDFToPDF() should replicate the pages so that the
downstream raster chain rasterises three copies.
Actual behaviour
Exactly one copy is printed, regardless of the requested copy count. Reproducible both from
lp -n N and from GUI print dialogs, so it is not an application-side issue.
Debug log (cupsctl --debug-logging)
D [01/Sep/2026:00:08:54 +0300] [Job 414] rastertosnailtspl-xprinter (application/vnd.cups-raster to printer/Xprinter_XP-420B, cost 0)
I [01/Sep/2026:00:08:54 +0300] [Job 414] Started filter /usr/lib/cups/filter/rastertosnailtspl-xprinter (PID 65037)
D [01/Sep/2026:00:08:54 +0300] [Job 414] ppdFilterLoadPPD: Last filter determined by the PPD: rastertosnailtspl-xprinter; Final data MIME type: application/vnd.cups-raster => PDF filter will not log pages in page_log.
D [01/Sep/2026:00:08:54 +0300] [Job 414] ppdFilterUniversal: application/vnd.cups-raster 0 rastertosnailtspl-xprinter
D [01/Sep/2026:00:08:54 +0300] [Job 414] cfFilterUniversal: Adding pdftopdf to chain
D [01/Sep/2026:00:08:54 +0300] [Job 414] cfFilterChain: Running filter: pdftopdf
D [01/Sep/2026:00:08:54 +0300] [Job 414] Set job-printer-state-message to "cfFilterChain: Running filter: pdftopdf", current level=INFO
D [01/Sep/2026:00:08:54 +0300] [Job 414] cfFilterChain: pdftopdf (PID 65043) started.
D [01/Sep/2026:00:08:54 +0300] [Job 414] Set job-printer-state-message to "cfFilterChain: pdftopdf (PID 65043) started.", current level=INFO
D [01/Sep/2026:00:08:54 +0300] [Job 414] cfFilterChain: pdftopdf completed with status 0.
D [01/Sep/2026:00:08:54 +0300] [Job 414] cfFilterGhostscript: Ghostscript command line: gs -dQUIET -dSAFER -dNOPAUSE -dBATCH -dNOINTERPOLATE -dNOMEDIAATTRS -dUsePDFX3Profile -sstdout=%stderr -sOutputFile=%stdout -sDEVICE=cups -r203x203 -dDEVICEWIDTHPOINTS=288 -dDEVICEHEIGHTPOINTS=432 -dcupsBitsPerColor=8 -dcupsColorOrder=0 -dcupsColorSpace=3 -dcupsRowCount=8 -scupsRenderingIntent=auto -scupsPageSizeName=4x6.Borderless -dcupsManualCopies -I/usr/share/cups/fonts -c '<< /.HWMargins[0.000000 0.000000 0.000000 0.000000] /Margins[0 0]>>setpagedevice' -f -_
D [01/Sep/2026:00:08:55 +0300] [Job 414] cfFilterChain: pdftopdf (PID 65043) exited with no errors.
D [01/Sep/2026:00:08:55 +0300] [Job 414] Set job-printer-state-message to "cfFilterChain: pdftopdf (PID 65043) exited with no errors.", current level=INFO
D [01/Sep/2026:00:08:55 +0300] [Job 414] PID 65037 (/usr/lib/cups/filter/rastertosnailtspl-xprinter) exited with no errors.
Two things stand out:
pdftopdf is added to the chain and exits cleanly, but the document handed to Ghostscript
evidently still contains a single copy.
- The Ghostscript command line carries
-dcupsManualCopies but no copy count, so no copies can
be produced downstream either — the copies are silently lost between the job attributes and the
rasteriser.
Workaround
Confirmed: downgrading libcupsfilters to 2.1.1 restores correct multi-copy printing with the
same PPD, same queue and same vendor filter, with no other changes to the system. Re-installing
2.2.1 brings the single-copy behaviour back.
pacman -U /var/cache/pacman/pkg/libcupsfilters-2.1.1-4.4-x86_64.pkg.tar.zst
systemctl restart cups
Additional notes
This configuration — a classic (non-driverless) CUPS raster driver relying on
*cupsManualCopies: True for software copy generation — may not be covered by the new
cupsfilters/test-filter-cases.txt CI cases added in 2.2.0. A regression test asserting that
cfFilterPDFToPDF() multiplies the page count when num-copies > 1 and
cupsManualCopies is true would catch this.
Happy to provide additional debug logs, the full PPD, or to test patches.
pdftopdf (cfFilterPDFToPDF) no longer generates soft copies with
*cupsManualCopies: True— regression in libcupsfilters 2.2.xSummary
After upgrading libcupsfilters 2.1.1 → 2.2.1, printing with
copies > 1to a raster-driverqueue produces exactly one copy. The queue uses a classic CUPS raster driver
(
*cupsFilter: "application/vnd.cups-raster 0 rastertosnailtspl-xprinter") whose PPD has*cupsManualCopies: True, so the copies must be produced in software bypdftopdf/cfFilterPDFToPDF().pdftopdfruns and exits with status 0, but the page count is not multiplied: Ghostscript issubsequently invoked without any copy count (no
/NumCopies), and only a single copy reachesthe printer.
Nothing else changed on the system: the same queue, same PPD and same vendor filter worked
correctly with libcupsfilters 2.1.1. Downgrading
libcupsfiltersback to 2.1.1 is the only changeneeded to restore correct behaviour.
libcupsfilters 2.2.0 rewrote
cfFilterPDFToPDF()from C++/QPDF to C/PDFio, which appears to bewhere the regression was introduced:
https://openprinting.github.io/libcupsfilters-2.2.0
Environment
2:2.4.19-12.0.1-2.12.1.1-2.12.2.1-2.1(broken) /2.1.1-4.4(works)xprinter-cups3.13.55-2 (vendor CUPS raster filterrastertosnailtspl-xprinter)cfFilterGhostscriptRelevant PPD lines:
Exact upgrade timestamp from
/var/log/pacman.log:The breakage was noticed the same day.
Steps to reproduce
Set up a CUPS queue with a classic raster driver whose PPD contains
*cupsManualCopies: Trueand a single*cupsFilter: "application/vnd.cups-raster 0 <vendor filter>".Submit a job with more than one copy, e.g.:
Observe the output.
Expected behaviour
Three copies are printed. Because the printer cannot generate copies in hardware and
*cupsManualCopies: Trueis set,cfFilterPDFToPDF()should replicate the pages so that thedownstream raster chain rasterises three copies.
Actual behaviour
Exactly one copy is printed, regardless of the requested copy count. Reproducible both from
lp -n Nand from GUI print dialogs, so it is not an application-side issue.Debug log (
cupsctl --debug-logging)Two things stand out:
pdftopdfis added to the chain and exits cleanly, but the document handed to Ghostscriptevidently still contains a single copy.
-dcupsManualCopiesbut no copy count, so no copies canbe produced downstream either — the copies are silently lost between the job attributes and the
rasteriser.
Workaround
Confirmed: downgrading
libcupsfiltersto 2.1.1 restores correct multi-copy printing with thesame PPD, same queue and same vendor filter, with no other changes to the system. Re-installing
2.2.1 brings the single-copy behaviour back.
Additional notes
This configuration — a classic (non-driverless) CUPS raster driver relying on
*cupsManualCopies: Truefor software copy generation — may not be covered by the newcupsfilters/test-filter-cases.txtCI cases added in 2.2.0. A regression test asserting thatcfFilterPDFToPDF()multiplies the page count whennum-copies > 1andcupsManualCopiesis true would catch this.Happy to provide additional debug logs, the full PPD, or to test patches.