Skip to content

Read report/label templates in binary mode - #12432

Merged
SchrodingersGat merged 2 commits into
inventree:masterfrom
impuls42:fix/report-template-binary-read
Jul 21, 2026
Merged

Read report/label templates in binary mode#12432
SchrodingersGat merged 2 commits into
inventree:masterfrom
impuls42:fix/report-template-binary-read

Conversation

@impuls42

Copy link
Copy Markdown
Contributor

Fix

file_from_template reads default report and label templates in text mode, so the resulting ContentFile reports its size as a character count. For a template with multi-byte UTF-8 characters that count is smaller than the encoded byte length, and django-storages sends it as the Content-Length. Backblaze B2 and other strict S3 backends reject the upload with IncompleteBody. AWS S3 tolerates the mismatch, so the bug is not visible there.

inventree_transfer_order_report.html is the only default template with a non-ASCII character (1458 chars, 1460 bytes), so its upload fails during create_default_reports, the transaction rolls back, and it is retried on every startup.

Reading the file in binary mode makes ContentFile.size match the uploaded bytes.

Fixes #12431

Testing

Reproduced on a live instance backed by Backblaze B2. Before the change, create_default_reports fails for the transfer-order template on every startup with IncompleteBody. After the change the template is created and the error is gone. Confirmed the mechanism in a shell for the same file: ContentFile(open(path, 'r').read()) fails, ContentFile(open(path, 'rb').read()) succeeds.

The mismatch only shows up against an S3 backend that enforces Content-Length, so it is not reproducible against the local storage used in CI.

@netlify

netlify Bot commented Jul 20, 2026

Copy link
Copy Markdown

Deploy Preview for inventree-web-pui-preview ready!

Name Link
🔨 Latest commit 44b845b
🔍 Latest deploy log https://app.netlify.com/projects/inventree-web-pui-preview/deploys/6a5f1ddc2b44b000088a6c07
😎 Deploy Preview https://deploy-preview-12432--inventree-web-pui-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 98 (🟢 up 1 from production)
Accessibility: 81 (no change from production)
Best Practices: 100 (no change from production)
SEO: 78 (no change from production)
PWA: -
View the detailed breakdown and full score reports
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@impuls42
impuls42 force-pushed the fix/report-template-binary-read branch from 3c24d4e to d8c143b Compare July 20, 2026 23:05
@impuls42

Copy link
Copy Markdown
Contributor Author

Updated after a self-review:

  • Switched to Path.read_bytes() instead of open('rb').read(), so the file handle is closed rather than relying on refcounting.
  • Added a regression test in report/tests.py asserting that file_from_template sizes the ContentFile by the file's byte length. It fails on the old text-mode read (character count) and passes with this change, and it needs no S3 backend.

@SchrodingersGat SchrodingersGat added bug Identifies a bug which needs to be addressed report Report/Label generation backport Apply this label to a PR to enable auto-backport action backport-to-1.4.x labels Jul 20, 2026
@SchrodingersGat SchrodingersGat added this to the 1.5.0 milestone Jul 20, 2026
@SchrodingersGat

Copy link
Copy Markdown
Member

@impuls42 thanks for the fix, this seems clean

@SchrodingersGat

Copy link
Copy Markdown
Member

This is the same issue as #12410

@SchrodingersGat

Copy link
Copy Markdown
Member

@impuls42 can you please add some testing against different text encodings as per the comments in #12410

@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.88%. Comparing base (b723f5d) to head (44b845b).

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #12432   +/-   ##
=======================================
  Coverage   86.87%   86.88%           
=======================================
  Files        1442     1442           
  Lines       94942    94971   +29     
  Branches    11101    11101           
=======================================
+ Hits        82482    82511   +29     
  Misses      12395    12395           
  Partials       65       65           
Flag Coverage Δ
backend 91.07% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
Backend Apps 92.57% <100.00%> (+<0.01%) ⬆️
Backend General 93.49% <ø> (ø)
Frontend 79.66% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@impuls42

Copy link
Copy Markdown
Contributor Author

Added a regression test (test_file_from_template_is_encoding_agnostic) that runs file_from_template over content in utf-8, utf-16 and latin-1 and asserts the ContentFile is byte-identical to the file on disk, with the size equal to the byte length. The utf cases include multi-byte characters where the byte length differs from the character count, which is the mismatch the old text-mode read produced. Reading the raw bytes never decodes, so non-English content can't be mis-sized or corrupted regardless of the file's encoding.

@impuls42
impuls42 force-pushed the fix/report-template-binary-read branch from 8ade6ab to 83b3461 Compare July 21, 2026 07:20
impuls42 added 2 commits July 21, 2026 09:20
file_from_template read the template in text mode and wrapped the string
in a ContentFile. The ContentFile size then reflected the character count,
which differs from the UTF-8 byte length for any template that contains
multi-byte characters. Strict S3 implementations such as Backblaze B2
validate the Content-Length header and reject the upload with an
IncompleteBody error. AWS S3 tolerates the mismatch, so the problem is
not visible there.

inventree_transfer_order_report.html is 1458 characters but 1460 bytes.
Its upload fails during create_default_reports, the transaction rolls
back, and the default template is recreated and fails again on every
startup.

Use Path.read_bytes() so the ContentFile size matches the uploaded bytes
and the file handle is closed. Add a regression test asserting the size
equals the file's byte length.
@impuls42
impuls42 force-pushed the fix/report-template-binary-read branch from 83b3461 to 44b845b Compare July 21, 2026 07:20
@SchrodingersGat
SchrodingersGat merged commit ce47cda into inventree:master Jul 21, 2026
42 checks passed
@SchrodingersGat

Copy link
Copy Markdown
Member

@impuls42 thanks for the contribution!

@github-actions

Copy link
Copy Markdown
Contributor

💚 All backports created successfully

Status Branch Result
1.4.x

Questions ?

Please refer to the Backport tool documentation and see the Github Action logs for details

SchrodingersGat pushed a commit that referenced this pull request Jul 23, 2026
* Read report/label templates in binary mode

file_from_template read the template in text mode and wrapped the string
in a ContentFile. The ContentFile size then reflected the character count,
which differs from the UTF-8 byte length for any template that contains
multi-byte characters. Strict S3 implementations such as Backblaze B2
validate the Content-Length header and reject the upload with an
IncompleteBody error. AWS S3 tolerates the mismatch, so the problem is
not visible there.

inventree_transfer_order_report.html is 1458 characters but 1460 bytes.
Its upload fails during create_default_reports, the transaction rolls
back, and the default template is recreated and fails again on every
startup.

Use Path.read_bytes() so the ContentFile size matches the uploaded bytes
and the file handle is closed. Add a regression test asserting the size
equals the file's byte length.

* Test file_from_template across text encodings

(cherry picked from commit ce47cda)

Co-authored-by: Alex K <alex@sengine.cloud>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport Apply this label to a PR to enable auto-backport action backport-to-1.4.x bug Identifies a bug which needs to be addressed report Report/Label generation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Default report creation fails on Backblaze B2 with IncompleteBody

2 participants