This is why "Add something new" could not create a product. It was not the upload limit raised in #14 — the post never got as far as multipart parsing.
The cause
Thymeleaf inserts the hidden _csrf input while it processes a th:action. Five forms were written with a plain action=, so Thymeleaf passed the tag through untouched and they posted with no token. Spring Security answers 403, Spring renders the site's own error page, and nothing is logged at ERROR — which is why the app log was completely clean while the form was broken.
That silence is what made this hard to see. Uploads looked like they were failing; in fact the request was rejected before any application code ran.
form
page
effect
Add an item
/admin
could not create a product
Add a category
/admin
could not add a category
Add a catering table
/admin/catering
could not add a table
Page notes
/admin/catering
could not edit the terms
Sign out
admin layout, every page
had been failing the same way
Test
Forms are counted against tokens rather than named, so a form added later is covered without anyone remembering to extend the test. Before the fix, /admin rendered 89 forms and carried 86 tokens — the test failed with exactly that, which is what confirmed the diagnosis.
Both worth recording rather than leaving to be rediscovered:
The 403 probe I used to "verify" the raised upload limit proved nothing. CSRF is checked before the body is parsed, which is precisely why a 5 KB body and a 3 MB body both returned 403. I read matching status codes as evidence the limit was live; they were matching for an unrelated reason.
The @ExceptionHandler added in #14 is narrower than its comment claims. It only catches an over-sized file if Tomcat has not already thrown during parameter parsing — and Tomcat does throw there when a filter reads a parameter first, which is what the original stack traces showed. Left alone here rather than widened on a guess; that path needs a real over-sized upload to characterise properly.
The raised limits themselves (15 MB / 60 MB) are still correct and still needed — a 1 MB cap would have blocked these uploads immediately after the CSRF fix.
**This is why "Add something new" could not create a product.** It was not the upload limit raised in #14 — the post never got as far as multipart parsing.
## The cause
Thymeleaf inserts the hidden `_csrf` input while it processes a `th:action`. Five forms were written with a plain `action=`, so Thymeleaf passed the tag through untouched and they posted **with no token**. Spring Security answers 403, Spring renders the site's own error page, and **nothing is logged at ERROR** — which is why the app log was completely clean while the form was broken.
That silence is what made this hard to see. Uploads looked like they were failing; in fact the request was rejected before any application code ran.
| form | page | effect |
|---|---|---|
| Add an item | `/admin` | **could not create a product** |
| Add a category | `/admin` | could not add a category |
| Add a catering table | `/admin/catering` | could not add a table |
| Page notes | `/admin/catering` | could not edit the terms |
| **Sign out** | admin layout, every page | had been failing the same way |
## Test
Forms are **counted against tokens** rather than named, so a form added later is covered without anyone remembering to extend the test. Before the fix, `/admin` rendered **89 forms and carried 86 tokens** — the test failed with exactly that, which is what confirmed the diagnosis.
69 tests passing.
## Two corrections to #14
Both worth recording rather than leaving to be rediscovered:
1. **The 403 probe I used to "verify" the raised upload limit proved nothing.** CSRF is checked before the body is parsed, which is precisely why a 5 KB body and a 3 MB body both returned 403. I read matching status codes as evidence the limit was live; they were matching for an unrelated reason.
2. **The `@ExceptionHandler` added in #14 is narrower than its comment claims.** It only catches an over-sized file if Tomcat has not already thrown during parameter parsing — and Tomcat does throw there when a filter reads a parameter first, which is what the original stack traces showed. Left alone here rather than widened on a guess; that path needs a real over-sized upload to characterise properly.
The raised limits themselves (15 MB / 60 MB) are still correct and still needed — a 1 MB cap would have blocked these uploads immediately after the CSRF fix.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
"Add something new" could not create a product. It was not the upload limit raised in #14: the post
never got as far as multipart parsing.
Thymeleaf inserts the hidden _csrf input while it processes a th:action. Five forms were written with
a plain action= instead, so Thymeleaf passed the tag through untouched and they posted with no token.
Spring Security answers 403, Spring renders the site's own error page, and NOTHING is logged at ERROR
-- which is why the app log was completely clean while the form was broken. From the outside it
looked like the upload silently failed; the request was rejected before any of our code ran.
The four that mattered: add an item, add a category, add a catering table, edit the page notes. The
fifth was Sign out in the admin layout, on every admin page, which had been failing the same way.
Counted rather than named in the test -- /admin renders 89 forms and carried 86 tokens -- so a form
added later is covered without anyone remembering to extend it.
Two notes on the previous change while this is fresh. The 403 probe I used to "verify" the raised
upload limit proved nothing: CSRF is checked before the body is parsed, which is exactly why a 5 KB
and a 3 MB body both came back 403. And the @ExceptionHandler added in #14 only catches an
over-sized file if Tomcat has not already thrown during parameter parsing, which it does when a
filter reads a parameter first -- so it is narrower than its comment claims. Left alone here rather
than widened on a guess; the size path needs a real over-sized upload to characterise.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
austin
merged commit 6cab5bb3f1 into main2026-07-27 19:50:48 -05:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
This is why "Add something new" could not create a product. It was not the upload limit raised in #14 — the post never got as far as multipart parsing.
The cause
Thymeleaf inserts the hidden
_csrfinput while it processes ath:action. Five forms were written with a plainaction=, so Thymeleaf passed the tag through untouched and they posted with no token. Spring Security answers 403, Spring renders the site's own error page, and nothing is logged at ERROR — which is why the app log was completely clean while the form was broken.That silence is what made this hard to see. Uploads looked like they were failing; in fact the request was rejected before any application code ran.
/admin/admin/admin/catering/admin/cateringTest
Forms are counted against tokens rather than named, so a form added later is covered without anyone remembering to extend the test. Before the fix,
/adminrendered 89 forms and carried 86 tokens — the test failed with exactly that, which is what confirmed the diagnosis.69 tests passing.
Two corrections to #14
Both worth recording rather than leaving to be rediscovered:
@ExceptionHandleradded in #14 is narrower than its comment claims. It only catches an over-sized file if Tomcat has not already thrown during parameter parsing — and Tomcat does throw there when a filter reads a parameter first, which is what the original stack traces showed. Left alone here rather than widened on a guess; that path needs a real over-sized upload to characterise properly.The raised limits themselves (15 MB / 60 MB) are still correct and still needed — a 1 MB cap would have blocked these uploads immediately after the CSRF fix.
🤖 Generated with Claude Code