Bug description
PR #9282 (fixing #6860) added a try/catch around YAML parsing in FormSubmissionsStore::makeItemFromFile() to prevent invalid form submissions from breaking the CP. However, there is a code path that bypasses this protection.
When a form submission contains non-UTF-8 bytes (e.g. control characters from copy-paste, or spam bots injecting binary data), Symfony's YAML dumper stores the value using the !!binary tag with base64 encoding. This is valid YAML, so it parses successfully — the ParseException catch doesn't trigger.
The error occurs later when the CP tries to return the paginated JSON response. JsonResponse::setData() calls json_encode(), which throws an InvalidArgumentException: Malformed UTF-8 characters, possibly incorrectly encoded. This crashes the entire forms listing — not just the single bad entry.
Stack trace (abbreviated):
InvalidArgumentException: Malformed UTF-8 characters, possibly incorrectly encoded
at vendor/laravel/framework/src/Illuminate/Http/JsonResponse.php:89
#0 symfony/http-foundation/JsonResponse.php(49): JsonResponse->setData()
#1 laravel/framework/.../JsonResponse.php(31): JsonResponse->__construct()
#2 laravel/framework/.../ResponseFactory.php(104): JsonResponse->__construct()
#3 laravel/framework/.../PaginatedResourceResponse.php(17): ResponseFactory->json()
#4 laravel/framework/.../ResourceCollection.php(133): PaginatedResourceResponse->toResponse()
How to reproduce
- Create a form in Statamic
- Create a YAML submission file with a !!binary tagged field containing bytes that are invalid UTF-8 when decoded. For example:
name: 'Test User'
email: test@example.com
message: !!binary dGVzdCBtZXNzYWdlIHdpdGggYmFkIGJ5dGVzOiDtoL3tsYk=
Logs
[2026-04-07 13:41:44] local.ERROR: Malformed UTF-8 characters, possibly incorrectly encoded {"userId":"639ec853-938f-4b60-9bb8-e3816ac6fd26","exception":"[object] (InvalidArgumentException(code: 0): Malformed UTF-8 characters, possibly incorrectly encoded at /home/ploi/site_url/vendor/laravel/framework/src/Illuminate/Http/JsonResponse.php:89)
[stacktrace]
#0 symfony/http-foundation/JsonResponse.php(49): Illuminate\\Http\\JsonResponse->setData()
#1 laravel/framework/src/Illuminate/Http/JsonResponse.php(31): Symfony\\Component\\HttpFoundation\\JsonResponse->__construct()
#2 laravel/framework/src/Illuminate/Routing/ResponseFactory.php(104): Illuminate\\Http\\JsonResponse->__construct()
#3 laravel/framework/src/Illuminate/Http/Resources/Json/PaginatedResourceResponse.php(17): Illuminate\\Routing\\ResponseFactory->json()
#4 laravel/framework/src/Illuminate/Http/Resources/Json/ResourceCollection.php(133): Illuminate\\Http\\Resources\\Json\\PaginatedResourceResponse->toResponse()
Environment
Environment
Laravel Version: 12.7.2
PHP Version: 8.4.11
Composer Version: 2.9.5
Environment: local
Debug Mode: OFF
Maintenance Mode: OFF
Cache
Config: NOT CACHED
Events: NOT CACHED
Routes: NOT CACHED
Views: NOT CACHED
Drivers
Broadcasting: reverb
Cache: file
Database: sqlite
Logs: stack / single
Mail: mailgun
Queue: sync
Session: file
Statamic
Addons: 1
Sites: 1
Stache Watcher: Enabled (auto)
Static Caching: Disabled
Version: 5.63.0 PRO
Installation
Existing Laravel app
Additional details
The existing try/catch in FormSubmissionsStore::makeItemFromFile() (added in PR #9282)
only catches Statamic\Yaml\ParseException. The !!binary YAML tag is valid YAML, so it
parses without error. The decoded binary data then passes through to the CP's JSON
response where json_encode() throws InvalidArgumentException.
This means any form submission containing non-UTF-8 bytes (common from spam bots or
copy-pasted text from Word/Google Docs containing control characters) will completely
break the CP forms listing for that form.
We had 25 spam submissions that brought down the entire forms section. The workaround
was to delete the offending YAML files and clear the Stache cache.
Bug description
PR #9282 (fixing #6860) added a try/catch around YAML parsing in FormSubmissionsStore::makeItemFromFile() to prevent invalid form submissions from breaking the CP. However, there is a code path that bypasses this protection.
When a form submission contains non-UTF-8 bytes (e.g. control characters from copy-paste, or spam bots injecting binary data), Symfony's YAML dumper stores the value using the !!binary tag with base64 encoding. This is valid YAML, so it parses successfully — the ParseException catch doesn't trigger.
The error occurs later when the CP tries to return the paginated JSON response. JsonResponse::setData() calls json_encode(), which throws an InvalidArgumentException: Malformed UTF-8 characters, possibly incorrectly encoded. This crashes the entire forms listing — not just the single bad entry.
Stack trace (abbreviated):
How to reproduce
Logs
[2026-04-07 13:41:44] local.ERROR: Malformed UTF-8 characters, possibly incorrectly encoded {"userId":"639ec853-938f-4b60-9bb8-e3816ac6fd26","exception":"[object] (InvalidArgumentException(code: 0): Malformed UTF-8 characters, possibly incorrectly encoded at /home/ploi/site_url/vendor/laravel/framework/src/Illuminate/Http/JsonResponse.php:89) [stacktrace] #0 symfony/http-foundation/JsonResponse.php(49): Illuminate\\Http\\JsonResponse->setData() #1 laravel/framework/src/Illuminate/Http/JsonResponse.php(31): Symfony\\Component\\HttpFoundation\\JsonResponse->__construct() #2 laravel/framework/src/Illuminate/Routing/ResponseFactory.php(104): Illuminate\\Http\\JsonResponse->__construct() #3 laravel/framework/src/Illuminate/Http/Resources/Json/PaginatedResourceResponse.php(17): Illuminate\\Routing\\ResponseFactory->json() #4 laravel/framework/src/Illuminate/Http/Resources/Json/ResourceCollection.php(133): Illuminate\\Http\\Resources\\Json\\PaginatedResourceResponse->toResponse()Environment
Installation
Existing Laravel app
Additional details
The existing try/catch in FormSubmissionsStore::makeItemFromFile() (added in PR #9282)
only catches Statamic\Yaml\ParseException. The !!binary YAML tag is valid YAML, so it
parses without error. The decoded binary data then passes through to the CP's JSON
response where json_encode() throws InvalidArgumentException.
This means any form submission containing non-UTF-8 bytes (common from spam bots or
copy-pasted text from Word/Google Docs containing control characters) will completely
break the CP forms listing for that form.
We had 25 spam submissions that brought down the entire forms section. The workaround
was to delete the offending YAML files and clear the Stache cache.