Content
Updated by Christophe Bliard 5 days ago
###
This bug was found through AppSignal which reported errors in at least 2 environments since 16.5:
1. prod-aws-de-bim: [https://appsignal.com/openproject-gmbh/sites/6813558755b0b20ed373594d/exceptions/incidents/1016](https://appsignal.com/openproject-gmbh/sites/6813558755b0b20ed373594d/exceptions/incidents/1016)
2. prod-aws-de-community: [https://appsignal.com/openproject-gmbh/sites/673c529383eb67b55471dda2/exceptions/incidents/1158](https://appsignal.com/openproject-gmbh/sites/673c529383eb67b55471dda2/exceptions/incidents/1158)
3. prod-aws-de-trials1: [https://appsignal.com/openproject-gmbh/sites/673c8be183eb67dcd6c4e75d/exceptions/incidents/1415](https://appsignal.com/openproject-gmbh/sites/673c8be183eb67dcd6c4e75d/exceptions/incidents/1415)
4. prod-aws-de-vips1: [https://appsignal.com/openproject-gmbh/sites/674718f1d2a5e4a7cb8b2298/exceptions/incidents/1242](https://appsignal.com/openproject-gmbh/sites/674718f1d2a5e4a7cb8b2298/exceptions/incidents/1242)
5. prod-aws-de-vips2: [https://appsignal.com/openproject-gmbh/sites/67c5518749a999507a2c1cef/exceptions/incidents/1014](https://appsignal.com/openproject-gmbh/sites/67c5518749a999507a2c1cef/exceptions/incidents/1014)
6. 2. prod-aws-de-vips3: [https://appsignal.com/openproject-gmbh/sites/681222e4e96fb49ca261a080/exceptions/incidents/538](https://appsignal.com/openproject-gmbh/sites/681222e4e96fb49ca261a080/exceptions/incidents/538)
7. prod-aws-de-vips4: [https://appsignal.com/openproject-gmbh/sites/6813715a55b0b20ed373597c/exceptions/incidents/1167](https://appsignal.com/openproject-gmbh/sites/6813715a55b0b20ed373597c/exceptions/incidents/1167)
8. prod-aws-de-vips5: [https://appsignal.com/openproject-gmbh/sites/681379ae55b0b20ed3735994/exceptions/incidents/1155](https://appsignal.com/openproject-gmbh/sites/681379ae55b0b20ed3735994/exceptions/incidents/1155)
9. <br>
10. edge-aws-de-trials2: [https://appsignal.com/openproject-gmbh/sites/673aff9f83eb6776b27e7743/exceptions/incidents/1258](https://appsignal.com/openproject-gmbh/sites/673aff9f83eb6776b27e7743/exceptions/incidents/1258)
###
### Steps to reproduce
The error occurs after uploading a file. A background job extracts text from the attachment and index it so that it can be searched. Sometimes, this produces a "FrozenError".
Here are some reproduction steps with a jped file
1. Use an OpenProject installation having tesseract installed in `/usr/bin/tesseract`
2. Upload the sample jpeg file `sample_1280×853.jpeg` attached to this bug
3. Search for job output in log file. Search for `Attachments::ExtractFulltextJob`.
### What is the buggy behavior?
* The job reports a `FrozenError` with a stacktrace looking like this:
```text
E, [2025-10-08T15:30:54.037434 #80081] ERROR -- : [ActiveJob] [Attachments::ExtractFulltextJob] [47a65584-46ba-44e9-8c06-3658859730f6] Error performing Attachments::ExtractFulltextJob (Job ID: 47a65584-46ba-44e9-8c06-3658859730f6) from GoodJob(default) in 211.86ms: FrozenE
rror (can't modify frozen String: ""):
/Users/cbliard/.local/share/mise/installs/ruby/3.4.5/lib/ruby/gems/3.4.0/gems/plaintext-0.3.4/lib/plaintext/resolver.rb:41:in 'String#gsub!'
/Users/cbliard/.local/share/mise/installs/ruby/3.4.5/lib/ruby/gems/3.4.0/gems/plaintext-0.3.4/lib/plaintext/resolver.rb:41:in 'Plaintext::Resolver#text'
/Users/cbliard/code/opf/openproject/release-16-5/app/workers/attachments/extract_fulltext_job.rb:61:in 'Attachments::ExtractFulltextJob#init'
/Users/cbliard/code/opf/openproject/release-16-5/app/workers/attachments/extract_fulltext_job.rb:46:in 'Attachments::ExtractFulltextJob#perform'
/Users/cbliard/.local/share/mise/installs/ruby/3.4.5/lib/ruby/gems/3.4.0/gems/activejob-8.0.2.1/lib/active_job/execution.rb:68:in 'block in ActiveJob::Execution#_perform_job'
/Users/cbliard/.local/share/mise/installs/ruby/3.4.5/lib/ruby/gems/3.4.0/gems/activesupport-8.0.2.1/lib/active_support/callbacks.rb:120:in 'block in ActiveSupport::Callbacks#run_callbacks'
/Users/cbliard/code/opf/openproject/release-16-5/app/workers/shared_job_setup.rb:59:in 'block in SharedJobSetup#prepare_job_context'
/Users/cbliard/code/opf/openproject/release-16-5/app/workers/shared_job_setup.rb:76:in 'SharedJobSetup#with_clean_request_store'
/Users/cbliard/code/opf/openproject/release-16-5/app/workers/shared_job_setup.rb:55:in 'SharedJobSetup#prepare_job_context'
```
### What is the expected behavior?
1. No error
### Analysis
The bug lies in the plaintext gem, in `Plaintext::Resolve#text` method.
`tesseract` is an OCR tool. When no text is found, it does not output anything and the command return `nil`. Then `plaintext` converts this output to a string by calling `.to_s`. And `nil.to_s` returns a frozen string (since ruby 2.7). When it calls `text.gsub!(/\s+/m, ' ')` later in the `text` method, the `FrozenError` occurs.
This problem occurs since 16.5.0 which introduced this change: [https://github.com/opf/openproject/commit/a69859f0ec7](https://github.com/opf/openproject/commit/a69859f0ec7). Before the error was rescued and logged. Now it is rescued, logged, and raised again to make any error during the text extraction process fail loudly so that we can notice and fix it.
###
###
### Environment information
**OpenProject installation type**
* Hosted cloud edition
**OpenProject version**
16.5.0
**Browser**
* [ ] Chrome
* [ ] Firefox
* [ ] Safari
* [ ] Mobile Safari
* [ ] Other (please specify)
**Operating System**
* [ ] Windows
* [ ] Mac OS X
* [ ] Mobile iOS
* [ ] Mobile Android
* [x] Linux (please specify distro)
* [ ] Chrome OS
* [ ] Other (please specify)
**Language**
_Please specify the browser language and the language of the OpenProject user for which the bug occurred._
This bug was found through AppSignal which reported errors in at least 2 environments since 16.5:
1. prod-aws-de-bim: [https://appsignal.com/openproject-gmbh/sites/6813558755b0b20ed373594d/exceptions/incidents/1016](https://appsignal.com/openproject-gmbh/sites/6813558755b0b20ed373594d/exceptions/incidents/1016)
2. prod-aws-de-community: [https://appsignal.com/openproject-gmbh/sites/673c529383eb67b55471dda2/exceptions/incidents/1158](https://appsignal.com/openproject-gmbh/sites/673c529383eb67b55471dda2/exceptions/incidents/1158)
3. prod-aws-de-trials1: [https://appsignal.com/openproject-gmbh/sites/673c8be183eb67dcd6c4e75d/exceptions/incidents/1415](https://appsignal.com/openproject-gmbh/sites/673c8be183eb67dcd6c4e75d/exceptions/incidents/1415)
4. prod-aws-de-vips1: [https://appsignal.com/openproject-gmbh/sites/674718f1d2a5e4a7cb8b2298/exceptions/incidents/1242](https://appsignal.com/openproject-gmbh/sites/674718f1d2a5e4a7cb8b2298/exceptions/incidents/1242)
5. prod-aws-de-vips2: [https://appsignal.com/openproject-gmbh/sites/67c5518749a999507a2c1cef/exceptions/incidents/1014](https://appsignal.com/openproject-gmbh/sites/67c5518749a999507a2c1cef/exceptions/incidents/1014)
6.
7. prod-aws-de-vips4: [https://appsignal.com/openproject-gmbh/sites/6813715a55b0b20ed373597c/exceptions/incidents/1167](https://appsignal.com/openproject-gmbh/sites/6813715a55b0b20ed373597c/exceptions/incidents/1167)
8. prod-aws-de-vips5: [https://appsignal.com/openproject-gmbh/sites/681379ae55b0b20ed3735994/exceptions/incidents/1155](https://appsignal.com/openproject-gmbh/sites/681379ae55b0b20ed3735994/exceptions/incidents/1155)
9. <br>
10. edge-aws-de-trials2: [https://appsignal.com/openproject-gmbh/sites/673aff9f83eb6776b27e7743/exceptions/incidents/1258](https://appsignal.com/openproject-gmbh/sites/673aff9f83eb6776b27e7743/exceptions/incidents/1258)
### Steps to reproduce
The error occurs after uploading a file. A background job extracts text from the attachment and index it so that it can be searched. Sometimes, this produces a "FrozenError".
Here are some reproduction steps with a jped file
1. Use an OpenProject installation having tesseract installed in `/usr/bin/tesseract`
2. Upload the sample jpeg file `sample_1280×853.jpeg` attached to this bug
3. Search for job output in log file. Search for `Attachments::ExtractFulltextJob`.
### What is the buggy behavior?
* The job reports a `FrozenError` with a stacktrace looking like this:
```text
E, [2025-10-08T15:30:54.037434 #80081] ERROR -- : [ActiveJob] [Attachments::ExtractFulltextJob] [47a65584-46ba-44e9-8c06-3658859730f6] Error performing Attachments::ExtractFulltextJob (Job ID: 47a65584-46ba-44e9-8c06-3658859730f6) from GoodJob(default) in 211.86ms: FrozenE
rror (can't modify frozen String: ""):
/Users/cbliard/.local/share/mise/installs/ruby/3.4.5/lib/ruby/gems/3.4.0/gems/plaintext-0.3.4/lib/plaintext/resolver.rb:41:in 'String#gsub!'
/Users/cbliard/.local/share/mise/installs/ruby/3.4.5/lib/ruby/gems/3.4.0/gems/plaintext-0.3.4/lib/plaintext/resolver.rb:41:in 'Plaintext::Resolver#text'
/Users/cbliard/code/opf/openproject/release-16-5/app/workers/attachments/extract_fulltext_job.rb:61:in 'Attachments::ExtractFulltextJob#init'
/Users/cbliard/code/opf/openproject/release-16-5/app/workers/attachments/extract_fulltext_job.rb:46:in 'Attachments::ExtractFulltextJob#perform'
/Users/cbliard/.local/share/mise/installs/ruby/3.4.5/lib/ruby/gems/3.4.0/gems/activejob-8.0.2.1/lib/active_job/execution.rb:68:in 'block in ActiveJob::Execution#_perform_job'
/Users/cbliard/.local/share/mise/installs/ruby/3.4.5/lib/ruby/gems/3.4.0/gems/activesupport-8.0.2.1/lib/active_support/callbacks.rb:120:in 'block in ActiveSupport::Callbacks#run_callbacks'
/Users/cbliard/code/opf/openproject/release-16-5/app/workers/shared_job_setup.rb:59:in 'block in SharedJobSetup#prepare_job_context'
/Users/cbliard/code/opf/openproject/release-16-5/app/workers/shared_job_setup.rb:76:in 'SharedJobSetup#with_clean_request_store'
/Users/cbliard/code/opf/openproject/release-16-5/app/workers/shared_job_setup.rb:55:in 'SharedJobSetup#prepare_job_context'
```
### What is the expected behavior?
1. No error
### Analysis
The bug lies in the plaintext gem, in `Plaintext::Resolve#text` method.
`tesseract` is an OCR tool. When no text is found, it does not output anything and the command return `nil`. Then `plaintext` converts this output to a string by calling `.to_s`. And `nil.to_s` returns a frozen string (since ruby 2.7). When it calls `text.gsub!(/\s+/m, ' ')` later in the `text` method, the `FrozenError` occurs.
This problem occurs since 16.5.0 which introduced this change: [https://github.com/opf/openproject/commit/a69859f0ec7](https://github.com/opf/openproject/commit/a69859f0ec7). Before the error was rescued and logged. Now it is rescued, logged, and raised again to make any error during the text extraction process fail loudly so that we can notice and fix it.
###
###
### Environment information
**OpenProject installation type**
* Hosted cloud edition
**OpenProject version**
16.5.0
**Browser**
* [ ] Chrome
* [ ] Firefox
* [ ] Safari
* [ ] Mobile Safari
* [ ] Other (please specify)
**Operating System**
* [ ] Windows
* [ ] Mac OS X
* [ ] Mobile iOS
* [ ] Mobile Android
* [x] Linux (please specify distro)
* [ ] Chrome OS
* [ ] Other (please specify)
**Language**
_Please specify the browser language and the language of the OpenProject user for which the bug occurred._