Package version: v0.8.3
PHP version: 8.4.20
Laravel version: 13.23.0
Summary
Parsing certain PDFs throws a fatal TypeError from inside the PDF parser: strlen(): Argument #1 ($string) must be of type string, int given
Location
src/Parsers/PdfParser.php:353, in decodeHexViaCMap():
$charLen = strlen(array_key_first($cmap));
Root cause
$cmap maps glyph hex codes → characters. PHP auto-casts integer-like string array keys to int (e.g. the key "1234" is stored as int 1234; keys with a leading zero like "0041" stay strings). When the first CMap key is a purely-numeric hex code with no leading zero, array_key_first($cmap) returns an int, and under PHP 8's strict typing strlen(int) throws a TypeError instead of coercing.
This is data-dependent, so it only triggers on PDFs whose font CMap happens to start with such a code. Because TypeError extends Error (not Exception/PaperdocException), consumers catching PaperdocException cannot handle it — it escapes as a fatal error.
Stack trace (abridged)
PdfParser::decodeHexViaCMap() src/Parsers/PdfParser.php:353
PdfParser::parseTextBlockWithCtm() src/Parsers/PdfParser.php:733
PdfParser::extractTextLines() src/Parsers/PdfParser.php:603
PdfParser::parse() src/Parsers/PdfParser.php:74
DocumentManager::open() src/Support/DocumentManager.php:53
Suggested fix
Cast the key to string before measuring its length:
$charLen = strlen((string) array_key_first($cmap));
More broadly, $cmap keys should be treated as strings throughout decodeHexViaCMap() (the same int-key coercion could affect the isset($cmap[$code]) lookup on line 365, since $code from substr() is always a string while a matching key may be stored as an int). Consider building the CMap with string-forced keys, or normalizing keys with (string) at every access.
Expected behavior
A PDF with numeric-looking CMap keys should parse without error — or at minimum, an unreadable/malformed document should surface as a ParserException/PaperdocException rather than a native TypeError, so it can be caught with the library's documented exception hierarchy.
I unfortunately no longer have the PDF that caused the issue (due to holidays, the log file cycling already cleaned that out)
Package version: v0.8.3
PHP version: 8.4.20
Laravel version: 13.23.0
Summary
Parsing certain PDFs throws a fatal TypeError from inside the PDF parser:
strlen(): Argument #1 ($string) must be of type string, int givenLocation
src/Parsers/PdfParser.php:353, in decodeHexViaCMap():
Root cause
$cmap maps glyph hex codes → characters. PHP auto-casts integer-like string array keys to int (e.g. the key "1234" is stored as int 1234; keys with a leading zero like "0041" stay strings). When the first CMap key is a purely-numeric hex code with no leading zero, array_key_first($cmap) returns an int, and under PHP 8's strict typing strlen(int) throws a TypeError instead of coercing.
This is data-dependent, so it only triggers on PDFs whose font CMap happens to start with such a code. Because TypeError extends Error (not Exception/PaperdocException), consumers catching PaperdocException cannot handle it — it escapes as a fatal error.
Stack trace (abridged)
Suggested fix
Cast the key to string before measuring its length:
More broadly, $cmap keys should be treated as strings throughout decodeHexViaCMap() (the same int-key coercion could affect the isset($cmap[$code]) lookup on line 365, since $code from substr() is always a string while a matching key may be stored as an int). Consider building the CMap with string-forced keys, or normalizing keys with (string) at every access.
Expected behavior
A PDF with numeric-looking CMap keys should parse without error — or at minimum, an unreadable/malformed document should surface as a ParserException/PaperdocException rather than a native TypeError, so it can be caught with the library's documented exception hierarchy.
I unfortunately no longer have the PDF that caused the issue (due to holidays, the log file cycling already cleaned that out)