wdl
wdl copied to clipboard
runtime struct initialization from select_first()
Hello,
I'd like to use a boolean that states if I need to run Task2 or not. The problem is when I attempt to catch the optional output of this task, or fallback to another variable.
Error reported by miniwdl:
2022-01-24 14:07:54.828 wdl.w:Workflow workflow Workflow (iftest.wdl Ln 40 Col 1) failed :: dir: "[redacted]", error: "EvalError", message: "unusable runtime struct initializer (member type mismatch, lacking required member, or extra member)", node: "output-updatedStruct", pos: {"source": "[redacted]", "line": 56, "column": 34}
2022-01-24 14:07:54.829 wdl.w:Workflow aborting workflow
2022-01-24 14:07:54.829 miniwdl-run unusable runtime struct initializer (member type mismatch, lacking required member, or extra member) :: error: "EvalError", node: "output-updatedStruct", pos: {"source": "[redacted]", "line": 56, "column": 34}, dir: "[redacted]"
And the reproductible example:
version 1.1
struct MyStruct {
String prop1
Boolean prop2
}
task Task1 {
input {}
command <<<
echo "Hello"
>>>
output {
MyStruct myUpdatedStruct = object {
"prop1": read_string(stdout()),
"prop2": true
}
}
}
task Task2 {
input {
MyStruct myStruct
}
command <<<
echo ~{myStruct.prop1} + " world !"
>>>
output {
MyStruct myUpdatedStruct = object {
"prop1": read_string(stdout()),
"prop2": false
}
}
}
workflow Workflow {
input {
Boolean runTask2 = true
}
call Task1 as task1 {
}
if (runTask2) {
call Task2 as task2 {
input:
myStruct = task1.myUpdatedStruct
}
}
output {
MyStruct updatedStruct = select_first([task2.myUpdatedStruct, task1.myUpdatedStruct])
}
}
Am I doing something wrong ?
Thanks for your help :)
Not sure, but WDL 1.1 deprecated object
in favor of a specific struct type. I would try using the newer form instead. (It should be supported as it's deprecated in 1.1, not removed, but maybe the 1.1 support has a bug.)
output {
MyStruct myUpdatedStruct = MyStruct {
"prop1": read_string(stdout()),
"prop2": true
}
}
Thank you, I made the modification, that's way more elegant !
Unfortunately it didn't solve my problem as the error remains.
Do you personally use another type of pattern than select_first
to handle conditional tasks ?
Updated example:
version 1.1
struct MyStruct {
String prop1
Boolean prop2
}
task Task1 {
input {}
command <<<
echo "Hello"
>>>
output {
MyStruct myUpdatedStruct = MyStruct {
"prop1": read_string(stdout()),
"prop2": true
}
}
}
task Task2 {
input {
MyStruct myStruct
}
command <<<
echo ~{myStruct.prop1} + " world !"
>>>
output {
MyStruct myUpdatedStruct = MyStruct {
"prop1": read_string(stdout()),
"prop2": false
}
}
}
workflow Workflow {
input {
Boolean runTask2 = true
}
call Task1 as task1 {
}
if (runTask2) {
call Task2 as task2 {
input:
myStruct = task1.myUpdatedStruct
}
}
output {
MyStruct updatedStruct = select_first([task2.myUpdatedStruct, task1.myUpdatedStruct])
}
}
Object keys are not quoted. Change "prop1"
to prop1
.
Ah, good to know !
Not fixing the issue though 😜
Updated example:
version 1.1
struct MyStruct {
String prop1
Boolean prop2
}
task Task1 {
input {}
command <<<
echo "Hello"
>>>
output {
MyStruct myUpdatedStruct = MyStruct {
prop1: read_string(stdout()),
prop2: true
}
}
}
task Task2 {
input {
MyStruct myStruct
}
command <<<
echo ~{myStruct.prop1} + " world !"
>>>
output {
MyStruct myUpdatedStruct = MyStruct {
prop1: read_string(stdout()),
prop2: false
}
}
}
workflow Workflow {
input {
Boolean runTask2 = true
}
call Task1 as task1 {
}
if (runTask2) {
call Task2 as task2 {
input:
myStruct = task1.myUpdatedStruct
}
}
output {
MyStruct updatedStruct = select_first([task2.myUpdatedStruct, task1.myUpdatedStruct])
}
}
I don't believe that Cromwell yet supports the new struct literal syntax. So do:
MyStruct myUpdatedStruct = object {
prop1: read_string(stdout()),
prop2: true
}
@Melkaz It is entirely possible that this is a bug in miniwdl? @mlin WDYT?
I think the issue here is probably that task2
is undefined if runTask2
is false
. So task2.myUpdate
is essentially None.myUpdate
, which results in an error.
Instead, I think you can do select_first([task1, task2]).myUpdatedStruct
.