image datablocks fail to import multilayer exr layers that have a dot in the name. #89991

Closed
opened 2021-07-20 15:05:05 +02:00 by michael campbell · 28 comments

System Information
Operating system: Windows-10-10.0.19041-SP0 64 Bits
Graphics card: GeForce GTX 1070/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 461.92

Blender Version
Broken: version: 3.0.0 Alpha, branch: master, commit date: 2021-07-16 19:29, hash: 118803893e
Worked: (newest version of Blender that worked as expected)

Exact steps for others to reproduce the error

open this file in the Blender image editor or an image node in the compositor:

dots.dont.work.exr

The multilayer EXR contains the following layers as shown in Affinity:

image.png

when opening the file in Blender, all EXR layers that contain a dot in the name fail, as shown below. The image node is missing one of the EXR layers:

image.png

**System Information** Operating system: Windows-10-10.0.19041-SP0 64 Bits Graphics card: GeForce GTX 1070/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 461.92 **Blender Version** Broken: version: 3.0.0 Alpha, branch: master, commit date: 2021-07-16 19:29, hash: `118803893e` Worked: (newest version of Blender that worked as expected) **Exact steps for others to reproduce the error** open this file in the Blender image editor or an image node in the compositor: ![dots.dont.work.exr](https://archive.blender.org/developer/F10229921/dots.dont.work.exr) The multilayer EXR contains the following layers as shown in Affinity: ![image.png](https://archive.blender.org/developer/F10229941/image.png) when opening the file in Blender, all EXR layers that contain a dot in the name fail, as shown below. The image node is missing one of the EXR layers: ![image.png](https://archive.blender.org/developer/F10229944/image.png)

Added subscriber: @3di

Added subscriber: @3di
Member

Added subscriber: @lichtwerk

Added subscriber: @lichtwerk
Member

Changed status from 'Needs Triage' to: 'Confirmed'

Changed status from 'Needs Triage' to: 'Confirmed'
Member

Can confirm.

Can confirm.
Member

#71574 (OpenEXR layers from View Layers with names containing a period can't be read by Nuke) is related (if not a duplicate)

#71574 (OpenEXR layers from View Layers with names containing a period can't be read by Nuke) is related (if not a duplicate)

Probably not a duplicate, I guess that indicates Nuke also has the same bug....maybe they're both using the same function of the openexr library to import, whereas Affinity isn't?

Probably not a duplicate, I guess that indicates Nuke also has the same bug....maybe they're both using the same function of the openexr library to import, whereas Affinity isn't?
Member

Hm, here is a similar file that actually seems to work:
dots.do.work.exr
Rendered from:
#71574.blend

[philippo@lic3 build_linux_lite]$ exrheader /lichtwerk/01_projects/0072_BORG_BlenderFoundationTracker/BORG_Produktion/08_Bugtracker_reports/T89991/dots.do.work.exr 

file /lichtwerk/01_projects/0072_BORG_BlenderFoundationTracker/BORG_Produktion/08_Bugtracker_reports/T89991/dots.do.work.exr:

file format version: 2, flags 0x400
BlenderMultiChannel (type string): "Blender V2.55.1 and newer"
Camera (type string): "Camera"
Date (type string): "2021/07/20 15:46:33"
File (type string): "/lichtwerk/01_projects/0072_BORG_BlenderFoundationTracker/BORG_Produktion/08_Bugtracker_reports/T89991/T71574.blend"
Frame (type string): "1"
RenderTime (type string): "00:00.18"
Scene (type string): "Scene"
Time (type string): "00:00:00:01"
channels (type chlist):
    Composite.Combined.A, 32-bit floating-point, sampling 1 1
    Composite.Combined.B, 32-bit floating-point, sampling 1 1
    Composite.Combined.G, 32-bit floating-point, sampling 1 1
    Composite.Combined.R, 32-bit floating-point, sampling 1 1
    name no dots.Combined.A, 32-bit floating-point, sampling 1 1
    name no dots.Combined.B, 32-bit floating-point, sampling 1 1
    name no dots.Combined.G, 32-bit floating-point, sampling 1 1
    name no dots.Combined.R, 32-bit floating-point, sampling 1 1
    name no dots.Depth.Z, 32-bit floating-point, sampling 1 1
    name.with.dots.Combined.A, 32-bit floating-point, sampling 1 1
    name.with.dots.Combined.B, 32-bit floating-point, sampling 1 1
    name.with.dots.Combined.G, 32-bit floating-point, sampling 1 1
    name.with.dots.Combined.R, 32-bit floating-point, sampling 1 1
    name.with.dots.Depth.Z, 32-bit floating-point, sampling 1 1
compression (type compression): zip, multi-scanline blocks
cycles.name no dots.render_time (type string): "00:00.08"
cycles.name no dots.samples (type string): "4"
cycles.name no dots.synchronization_time (type string): "00:00.00"
cycles.name no dots.total_time (type string): "00:00.09"
cycles.name.with.dots.render_time (type string): "00:00.08"
cycles.name.with.dots.samples (type string): "4"
cycles.name.with.dots.synchronization_time (type string): "00:00.00"
cycles.name.with.dots.total_time (type string): "00:00.08"
dataWindow (type box2i): (0 0) - (959 539)
displayWindow (type box2i): (0 0) - (959 539)
lineOrder (type lineOrder): increasing y
pixelAspectRatio (type float): 1
screenWindowCenter (type v2f): (0 0)
screenWindowWidth (type float): 1
type (type string): "scanlineimage"

[philippo@lic3 build_linux_lite]$ exrheader /lichtwerk/01_projects/0072_BORG_BlenderFoundationTracker/BORG_Produktion/08_Bugtracker_reports/T89991/dots.dont.work.exr 

file /lichtwerk/01_projects/0072_BORG_BlenderFoundationTracker/BORG_Produktion/08_Bugtracker_reports/T89991/dots.dont.work.exr:

file format version: 2, flags 0x0
BlenderMultiChannel (type string): "Blender V2.55.1 and newer"
Date (type string): "2021/07/20 14:00:03"
File (type string): "E:\programming\blender\my addons\incomplete\auto_file_output\blend files\test_upstream.blend"
Scene (type string): "Scene"
channels (type chlist):
    name no dots.A, 32-bit floating-point, sampling 1 1
    name no dots.B, 32-bit floating-point, sampling 1 1
    name no dots.G, 32-bit floating-point, sampling 1 1
    name no dots.R, 32-bit floating-point, sampling 1 1
    name.with.dots.A, 32-bit floating-point, sampling 1 1
    name.with.dots.B, 32-bit floating-point, sampling 1 1
    name.with.dots.G, 32-bit floating-point, sampling 1 1
    name.with.dots.R, 32-bit floating-point, sampling 1 1
compression (type compression): none
dataWindow (type box2i): (0 0) - (1919 1079)
displayWindow (type box2i): (0 0) - (1919 1079)
lineOrder (type lineOrder): increasing y
pixelAspectRatio (type float): 1
screenWindowCenter (type v2f): (0 0)
screenWindowWidth (type float): 1
type (type string): "scanlineimage"
Hm, here is a similar file that actually seems to work: ![dots.do.work.exr](https://archive.blender.org/developer/F10229971/dots.do.work.exr) Rendered from: [#71574.blend](https://archive.blender.org/developer/F10229972/T71574.blend) ``` [philippo@lic3 build_linux_lite]$ exrheader /lichtwerk/01_projects/0072_BORG_BlenderFoundationTracker/BORG_Produktion/08_Bugtracker_reports/T89991/dots.do.work.exr file /lichtwerk/01_projects/0072_BORG_BlenderFoundationTracker/BORG_Produktion/08_Bugtracker_reports/T89991/dots.do.work.exr: file format version: 2, flags 0x400 BlenderMultiChannel (type string): "Blender V2.55.1 and newer" Camera (type string): "Camera" Date (type string): "2021/07/20 15:46:33" File (type string): "/lichtwerk/01_projects/0072_BORG_BlenderFoundationTracker/BORG_Produktion/08_Bugtracker_reports/T89991/T71574.blend" Frame (type string): "1" RenderTime (type string): "00:00.18" Scene (type string): "Scene" Time (type string): "00:00:00:01" channels (type chlist): Composite.Combined.A, 32-bit floating-point, sampling 1 1 Composite.Combined.B, 32-bit floating-point, sampling 1 1 Composite.Combined.G, 32-bit floating-point, sampling 1 1 Composite.Combined.R, 32-bit floating-point, sampling 1 1 name no dots.Combined.A, 32-bit floating-point, sampling 1 1 name no dots.Combined.B, 32-bit floating-point, sampling 1 1 name no dots.Combined.G, 32-bit floating-point, sampling 1 1 name no dots.Combined.R, 32-bit floating-point, sampling 1 1 name no dots.Depth.Z, 32-bit floating-point, sampling 1 1 name.with.dots.Combined.A, 32-bit floating-point, sampling 1 1 name.with.dots.Combined.B, 32-bit floating-point, sampling 1 1 name.with.dots.Combined.G, 32-bit floating-point, sampling 1 1 name.with.dots.Combined.R, 32-bit floating-point, sampling 1 1 name.with.dots.Depth.Z, 32-bit floating-point, sampling 1 1 compression (type compression): zip, multi-scanline blocks cycles.name no dots.render_time (type string): "00:00.08" cycles.name no dots.samples (type string): "4" cycles.name no dots.synchronization_time (type string): "00:00.00" cycles.name no dots.total_time (type string): "00:00.09" cycles.name.with.dots.render_time (type string): "00:00.08" cycles.name.with.dots.samples (type string): "4" cycles.name.with.dots.synchronization_time (type string): "00:00.00" cycles.name.with.dots.total_time (type string): "00:00.08" dataWindow (type box2i): (0 0) - (959 539) displayWindow (type box2i): (0 0) - (959 539) lineOrder (type lineOrder): increasing y pixelAspectRatio (type float): 1 screenWindowCenter (type v2f): (0 0) screenWindowWidth (type float): 1 type (type string): "scanlineimage" [philippo@lic3 build_linux_lite]$ exrheader /lichtwerk/01_projects/0072_BORG_BlenderFoundationTracker/BORG_Produktion/08_Bugtracker_reports/T89991/dots.dont.work.exr file /lichtwerk/01_projects/0072_BORG_BlenderFoundationTracker/BORG_Produktion/08_Bugtracker_reports/T89991/dots.dont.work.exr: file format version: 2, flags 0x0 BlenderMultiChannel (type string): "Blender V2.55.1 and newer" Date (type string): "2021/07/20 14:00:03" File (type string): "E:\programming\blender\my addons\incomplete\auto_file_output\blend files\test_upstream.blend" Scene (type string): "Scene" channels (type chlist): name no dots.A, 32-bit floating-point, sampling 1 1 name no dots.B, 32-bit floating-point, sampling 1 1 name no dots.G, 32-bit floating-point, sampling 1 1 name no dots.R, 32-bit floating-point, sampling 1 1 name.with.dots.A, 32-bit floating-point, sampling 1 1 name.with.dots.B, 32-bit floating-point, sampling 1 1 name.with.dots.G, 32-bit floating-point, sampling 1 1 name.with.dots.R, 32-bit floating-point, sampling 1 1 compression (type compression): none dataWindow (type box2i): (0 0) - (1919 1079) displayWindow (type box2i): (0 0) - (1919 1079) lineOrder (type lineOrder): increasing y pixelAspectRatio (type float): 1 screenWindowCenter (type v2f): (0 0) screenWindowWidth (type float): 1 type (type string): "scanlineimage" ```

hmm, in your file it doesn't show an output per layer, instead it changes the outputs based on the chosen layer. The functionality that my addon relies on, is to show all layers as outputs, otherwise it'll break a couple of months worth of programming.

image.png

hmm, in your file it doesn't show an output per layer, instead it changes the outputs based on the chosen layer. The functionality that my addon relies on, is to show all layers as outputs, otherwise it'll break a couple of months worth of programming. ![image.png](https://archive.blender.org/developer/F10229992/image.png)

i'm outputting the file from the compositor file output node by the way, whereas you're outputting it from a render animation.

i'm outputting the file from the compositor file output node by the way, whereas you're outputting it from a render animation.
Member

Added subscribers: @Jeroen-Bakker, @brecht

Added subscribers: @Jeroen-Bakker, @brecht
Member

Problem seems to be the assumption in imb_exr_split_channel_name / imb_exr_split_token that the whole name contains three tokens:

/* last token is channel identifier */
...
/* second token is pass name */
...
/* all preceding tokens combined as layer name */

see https://developer.blender.org/diffusion/B/browse/master/source/blender/imbuf/intern/openexr/openexr_api.cpp$1418
In your case, there is only a channel and pass, but no layer detected.
If that is the case, imb_exr_begin_read_mem will create a layer via imb_exr_get_layer (should this be called imb_exr_layer_ensure then?) -- and somewhere this seems to go wrong

Unsure how this should work:

  • should pass and layer be the same?
  • should we enforce a pass (e.g. "Combined") in this case?
  • should a layer and channels be permitted (without a pass)?

CC @Jeroen-Bakker
CC @brecht

Problem seems to be the assumption in `imb_exr_split_channel_name` / `imb_exr_split_token` that the whole name contains three tokens: ``` /* last token is channel identifier */ ... /* second token is pass name */ ... /* all preceding tokens combined as layer name */ ``` see https://developer.blender.org/diffusion/B/browse/master/source/blender/imbuf/intern/openexr/openexr_api.cpp$1418 In your case, there is only a `channel` and `pass`, but no `layer` detected. If that is the case, `imb_exr_begin_read_mem` will **create** a layer via `imb_exr_get_layer` (should this be called `imb_exr_layer_ensure` then?) -- and somewhere this seems to go wrong Unsure how this **should** work: - should `pass` and `layer` be the same? - should we enforce a `pass` (e.g. "Combined") in this case? - should a `layer` and `channels` be permitted (without a `pass`)? CC @Jeroen-Bakker CC @brecht

very strange:

Here's with all inputs not having dots. No option to choose a layer in the image node, they just all appear as outputs (which is imperative):

image.png

But if I change one of the inputs to have dots, then I get an option to choose layers, but only a single layer exists, and the letter after the final dot is taken to be the output...

image.png

I think maybe someone has gotten confused when adding multilayer to the file output node, and have taken inputs and layers to be the same thing. The correct functionality is to be able to specify the same layer for multiple inputs....although I'm not sure that explains the dot problem

very strange: Here's with all inputs not having dots. No option to choose a layer in the image node, they just all appear as outputs (which is imperative): ![image.png](https://archive.blender.org/developer/F10230010/image.png) But if I change one of the inputs to have dots, then I get an option to choose layers, but only a single layer exists, and the letter after the final dot is taken to be the output... ![image.png](https://archive.blender.org/developer/F10230016/image.png) I think maybe someone has gotten confused when adding multilayer to the file output node, and have taken inputs and layers to be the same thing. The correct functionality is to be able to specify the same layer for multiple inputs....although I'm not sure that explains the dot problem

This comment was removed by @3di

*This comment was removed by @3di*

This comment was removed by @3di

*This comment was removed by @3di*

OK, I found the problem. It's the file output node not adding any layer to the name:

it should be:

Layer . Name. File_format

so it's working when rendered from ctrl f12, because the output is:

name.with.dots.Combined.RGB

whereas the file output node is outputting:

name.with.dots.RGB (missing the layer)

so if the file output node isn't going to let the user specify a layer to assign the inputs to, then it should just add a layer name that doesn't contain any dots to the start of the string.

OK, I found the problem. It's the file output node not adding any layer to the name: it should be: Layer . Name. File_format so it's working when rendered from ctrl f12, because the output is: name.with.dots.Combined.RGB whereas the file output node is outputting: name.with.dots.RGB (missing the layer) so if the file output node isn't going to let the user specify a layer to assign the inputs to, then it should just add a layer name that doesn't contain any dots to the start of the string.
Member

Changed status from 'Confirmed' to: 'Needs Developer To Reproduce'

Changed status from 'Confirmed' to: 'Needs Developer To Reproduce'
Member

so if the file output node isn't going to let the user specify a layer to assign the inputs to, then it should just add 'Combined' between the name and the file_format.

either that, or one of these (permitting layer.channel - this is according to spec - and enforcing layer.pass.channel when reading -- or permit layer.channel as well which might be a bigger change since assumption atm is layer.pass.channel ):

In #89991#1193782, @lichtwerk wrote:
Unsure how this should work:

  • should pass and layer be the same?
  • should we enforce a pass (e.g. "Combined") in this case?
  • should a layer and channels be permitted (without a pass)?

CC @Jeroen-Bakker
CC @brecht

At this point, I think it would be good to get input from module devs.

> so if the file output node isn't going to let the user specify a layer to assign the inputs to, then it should just add 'Combined' between the name and the file_format. either that, or one of these (permitting `layer.channel` - this is according to spec - and enforcing `layer.pass.channel` when **reading** -- or permit `layer.channel` as well which might be a bigger change since assumption atm is `layer.pass.channel` ): > In #89991#1193782, @lichtwerk wrote: > Unsure how this **should** work: > - should `pass` and `layer` be the same? > - should we enforce a `pass` (e.g. "Combined") in this case? > - should a `layer` and `channels` be permitted (without a `pass`)? > > CC @Jeroen-Bakker > CC @brecht At this point, I think it would be good to get input from module devs.

yes, it should definitely follow the same convention as the rest of blender:

layer.pass.channel

as oppose to the current :

pass.channel

yes, it should definitely follow the same convention as the rest of blender: layer.pass.channel as oppose to the current : pass.channel

I can just manually add something without dots to the beginning of the input name for now. Would be great to have the file output node do that automatically though.

I can just manually add something without dots to the beginning of the input name for now. Would be great to have the file output node do that automatically though.

nope, still breaks if the pass has dots in it because the function that creates the image blocks when opening EXR's is searching from the right of the string, splitting it to get the channel, then searching from the right again and splitting it to get the pass, and then one more time to get the layer.

In order for it to work if the pass contains dots, the code that opens multilayer exr's it needs to do this instead:

x = full_layer_name
channel = x[ rfind('.') : ]
layer = x[ : x.find('.') ]
pass = x[ x.find('.') : x.rfind('.') ]

nope, still breaks if the pass has dots in it because the function that creates the image blocks when opening EXR's is searching from the right of the string, splitting it to get the channel, then searching from the right again and splitting it to get the pass, and then one more time to get the layer. In order for it to work if the pass contains dots, the code that opens multilayer exr's it needs to do this instead: x = full_layer_name channel = x[ rfind('.') : ] layer = x[ : x.find('.') ] pass = x[ x.find('.') : x.rfind('.') ]

First, I would recommend to not use dots in the names at all, as they are the standard separator for EXR and it will inevitably lead to problems in Blender or other software. On top of that, while the EXR specification mentions dots, a lot of other software deviates from that and uses underscores instead. So I would use neither.

For reading, the best Blender can do is tweak heuristics to get a better result in undefined cases. For writing, we could show a warning and/or replace the dots when writing EXR files to sidestep the problem.

When only two tokens are provided when reading an EXR file, they are pass and channel. These should not be interpreted as layer.

First, I would recommend to not use dots in the names at all, as they are the standard separator for EXR and it will inevitably lead to problems in Blender or other software. On top of that, while the EXR specification mentions dots, a lot of other software deviates from that and uses underscores instead. So I would use neither. For reading, the best Blender can do is tweak heuristics to get a better result in undefined cases. For writing, we could show a warning and/or replace the dots when writing EXR files to sidestep the problem. When only two tokens are provided when reading an EXR file, they are `pass` and `channel`. These should not be interpreted as `layer`.

Would it be possible to keep everything as it is, but just use the code I posted above, then it won't matter if there are dots in the pass name, and it'll continue to work under all circumstances it currently works for. In the case of there being only two tokens, then you could just have:

if pass == channel:

  pass = layer
  layer = None

I'm basically saving out AOV's via a file output node. If the user duplicates an AOV and doesn't realise Blender's auto renaming convention of adding .### after a duplicate AOV name, then Blender won't be able to re-open the saved EXRs.

Alternatively, the auto duplicate renaming could use _### instead of .###

Would it be possible to keep everything as it is, but just use the code I posted above, then it won't matter if there are dots in the pass name, and it'll continue to work under all circumstances it currently works for. In the case of there being only two tokens, then you could just have: if pass == channel: ``` pass = layer layer = None ``` I'm basically saving out AOV's via a file output node. If the user duplicates an AOV and doesn't realise Blender's auto renaming convention of adding .### after a duplicate AOV name, then Blender won't be able to re-open the saved EXRs. Alternatively, the auto duplicate renaming could use _### instead of .###

other software doesn't matter, the files generated will only ever be used by Blender.

other software doesn't matter, the files generated will only ever be used by Blender.

although the above alternative method I posted of getting the tokens from the string would also enable a user to import from other softwares that have dots in the pass name.

although the above alternative method I posted of getting the tokens from the string would also enable a user to import from other softwares that have dots in the pass name.

it would break again if the view layer has dots in it. Maybe the safest option is to enforce no dots in the aov and view layer names. Can't believe exr stores variables in the string, I thought it would use something like exr or json.

it would break again if the view layer has dots in it. Maybe the safest option is to enforce no dots in the aov and view layer names. Can't believe exr stores variables in the string, I thought it would use something like exr or json.

The current heuristic works well for Blender in many cases because the standard channel and pass names do not contain dots. The view layer name on the other hand is more likely to have dots, and is parsed correctly if you go from right to left. So I think that's pretty reasonable.

Avoiding automatic dots and warning against manually added dots in AOV names in Blender seems like a practical thing we can do.

The current heuristic works well for Blender in many cases because the standard channel and pass names do not contain dots. The view layer name on the other hand is more likely to have dots, and is parsed correctly if you go from right to left. So I think that's pretty reasonable. Avoiding automatic dots and warning against manually added dots in AOV names in Blender seems like a practical thing we can do.

This issue was referenced by 8e8932c8ff

This issue was referenced by 8e8932c8ff28ec1b1ac7af9254244d94b326b9b8

Changed status from 'Needs Developer To Reproduce' to: 'Resolved'

Changed status from 'Needs Developer To Reproduce' to: 'Resolved'
Brecht Van Lommel self-assigned this 2021-10-19 13:09:43 +02:00
Sign in to join this conversation.
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
4 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#89991
No description provided.