fix: drop the 10 MB cap on inserted images - #558
Conversation
Removes the client-side refusal (useImageInsert.js) and the matching server-side gate (upload_diagram_image) — neither the picker nor the endpoint reads a file's size any more. Whatever still limits an upload is below this app: the site's own max_file_size and the web server's request body limit, which this code has no way to see or mirror, so there is nothing useful left to check here. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
vibhavkatre
left a comment
There was a problem hiding this comment.
Two things before this merges.
The 10 MB cap does not become "no cap"
Frappe still refuses the file. File.check_max_file_size() (frappe/core/doctype/file/file.py) throws above get_max_file_size(), and frappe/app.py sets request.max_content_length to the same number. With no max_file_size in System Settings or site_config.json, that default is 25 MB. So this raises the ceiling from 10 MB to 25 MB on a default site — it does not remove it.
That makes the new test misleading:
it('does not refuse a large file — no size gate left client-side', ...)
const big = { type: 'image/png', name: 'huge.png', size: 200 * 1024 * 1024 }
expect(await useImageInsert(store).insert(big)).toBe('shape-1')FileUploadHandler is mocked, so this passes. Against a real site the same 200 MB file fails. Please name what the test actually pins — that the picker no longer reads file.size — rather than that a large file inserts.
The code comment needs the same correction: it names site_config.json, but the value is read from System Settings first, then frappe.conf, then a 25 MB default.
Removing the client pre-check is a UX regression
The comment you deleted said the gate existed so "a file it would refuse is refused here — with a reason — instead of costing an upload to find out". That reasoning still holds at 25 MB. A 40 MB photo now uploads all 40 MB before the server refuses it. On a slow connection that is a long wait for a failure the browser already had the information to predict.
Frappe publishes the real number — frappe.boot.max_file_size, and the whitelisted frappe.core.api.file.get_max_file_size. Reading that instead of hard-coding 10 MB keeps the fast, specific refusal and follows whatever the site is configured for, which is what the new comment says this file has no way to do.
uploadFailure does surface the server's message, so the failure is at least not silent — but it arrives after the upload rather than before it.
One question
There is no linked issue, and the comment says the gate was "dropped on request". Whose request, and was the ask "raise the cap" or "no cap at all"? If it was genuinely no limit, that is a site configuration change (max_file_size in site_config.json), not an app change. Worth confirming with @vibhavkatre before this lands.
frappe#558) Removing the client-side gate didn't remove a limit — Frappe's File doctype still refuses an oversized upload on insert (check_max_file_size), and the site's real number was never 10 MB to begin with; it's System Settings, then site_config.json, then a 25 MB default (get_max_file_size). So the client gate was refusing against a number that didn't match the server, and dropping it entirely just meant every oversized upload rides all the way to the server before it can find that out. Reads the real ceiling instead: draw/www/draw.py puts get_max_file_size() on the boot payload as window.max_file_size, alongside the existing csrf_token/socketio_port globals, and useImageInsert.js's refusal reads it (falling back to the same 25 MB default if the boot value is ever missing). The server-side gate stays dropped from upload_diagram_image — File.insert() already enforces it, so a bespoke copy could only drift. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Confidence Score: 5/5The PR appears safe to merge with no actionable defects identified. Client-side validation now follows the server-provided limit, while Frappe’s File insertion remains the authoritative enforcement boundary. Reviews (1): Last reviewed commit: "Merge branch 'main' into fix/image-uploa..." | Re-trigger Greptile |
vibhavkatre
left a comment
There was a problem hiding this comment.
This is the right shape now. The client no longer guesses at a limit: get_max_file_size() resolves System Settings → site_config.json → Frappe's own 25 MB default, and draw/www/draw.py puts that number on the boot payload, so the fast refusal is measured against the same value File.check_max_file_size will enforce. Dropping the bespoke gate from upload_diagram_image is right for the same reason — a second copy could only drift.
Checked: get_max_file_size() returns bytes, so the file.size > limit comparison is in the right units; the generated draw.html loops over boot and assigns window[key], so max_file_size reaches the browser without a template change; and the || FALLBACK_MAX_BYTES guard cannot be reached by a real configured value, since get_max_file_size already ORs to 25 MB itself.
The tests now stub window.max_file_size per case instead of asserting a hardcoded number, which pins the dynamic behaviour rather than one snapshot of it.
Merging.
Summary
useImageInsert.js— the picker no longer reads a file'ssizeat all.upload_diagram_image(draw/api/diagram.py).max_file_size, the web server's request-body limit) — this code has no way to see or mirror those, so there's nothing left here to check.Test plan
yarn vitest run— 1731 tests passing, including a new test asserting a 200MB file is no longer refused client-sideyarn lint— cleanbench run-tests(draw_diagram module) — 75 backend tests passing🤖 Generated with Claude Code