This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch 
gh-readonly-queue/main/pr-8885-ee1deb75fb16f0ead6c715fa9e52465157f85c51
in repository https://gitbox.apache.org/repos/asf/texera.git

commit ed724ebede6dba46f778e2adfd471ee07dcc251e
Author: Prateek Ganigi <[email protected]>
AuthorDate: Wed Oct 14 23:45:58 2026 +0000

    fix(workflow-operator): require b64_json to be a string before building a 
data URL (#8885)
    
    ### What changes were proposed in this PR?
    
    `ImageTaskCodegen.parsePython`'s `image-to-image` branch built a data
    URL from the provider's `b64_json` without checking it, so a malformed
    but valid-JSON 200 put an unrenderable value in the result column, a
    null field became the literal `data:image/png;base64,None`, with nothing
    to indicate why the image was blank.
    
    `b64_json` must now be a non-empty string; anything else falls through
    to `json.dumps(body)`, which is what the branch already did for
    unrecognised shapes.
    
    Scoped deliberately to `b64_json`, matching the issue. The sibling `url`
    lookups in the same branch have a comparable gap and are left for a
    separate issue.
    
    Not addressed: a `b64_json` that is a string but not valid base64 still
    yields an unrenderable data URL. Detecting that means decoding the value
    on every row, and corrupt-but-well-formed base64 would pass regardless,
    so the browser's rejection is unchanged either way. Same reasoning as
    #8872.
    
    ### Any related issues?
    
    Closes #8870
    
    ### How was this PR tested?
    
    Written test-first: a test asserting the string guard was added to
    `ImageTaskCodegenSpec` and fails against the current parse. The suite is
    at 155 tests, `PythonCodeRawInvalidTextSpec` py-compiles all 117
    operators, and `scalafmtCheck` and `scalafix --check` are clean.
    
    The generated parser was also run directly: a null or numeric `b64_json`
    now returns the serialized body, and a valid base64 payload still
    produces the same data URL as before.
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    Yes, this PR was co-authored with Claude in compliance with ASF policy.
    
    Co-authored-by: Xuan Gu <[email protected]>
---
 .../amber/operator/huggingFace/codegen/ImageTaskCodegen.scala    | 8 ++++++--
 .../operator/huggingFace/codegen/ImageTaskCodegenSpec.scala      | 9 +++++++++
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git 
a/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/huggingFace/codegen/ImageTaskCodegen.scala
 
b/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/huggingFace/codegen/ImageTaskCodegen.scala
index 201d7b1623..6662878b13 100644
--- 
a/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/huggingFace/codegen/ImageTaskCodegen.scala
+++ 
b/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/huggingFace/codegen/ImageTaskCodegen.scala
@@ -143,8 +143,12 @@ object ImageTaskCodegen extends TaskCodegen {
       |                            if outputs and isinstance(outputs[0], str) 
and outputs[0].startswith("http"):
       |                                return self._url_to_data_url(outputs[0])
       |                        if isinstance(data, list) and data and 
isinstance(data[0], dict):
-      |                            if "b64_json" in data[0]:
-      |                                return 
f"data:image/png;base64,{data[0]['b64_json']}"
+      |                            # b64_json comes straight from the 
provider: an unchecked
+      |                            # value reaches the cell as a data URL 
nothing can render,
+      |                            # e.g. "data:image/png;base64,None".
+      |                            b64 = data[0].get("b64_json")
+      |                            if isinstance(b64, str) and b64:
+      |                                return f"data:image/png;base64,{b64}"
       |                            if "url" in data[0]:
       |                                return 
self._url_to_data_url(data[0]["url"])
       |                return json.dumps(body)
diff --git 
a/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/huggingFace/codegen/ImageTaskCodegenSpec.scala
 
b/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/huggingFace/codegen/ImageTaskCodegenSpec.scala
index 0e026fdf0f..81518d8d0c 100644
--- 
a/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/huggingFace/codegen/ImageTaskCodegenSpec.scala
+++ 
b/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/huggingFace/codegen/ImageTaskCodegenSpec.scala
@@ -111,6 +111,15 @@ class ImageTaskCodegenSpec extends AnyFlatSpec with 
Matchers {
     out should include("data:image/png;base64,")
   }
 
+  // #8870: the image-to-image branch trusted whatever the provider returned, 
so a
+  // malformed 200 produced a data URL nothing can render — a null b64_json 
became
+  // the literal "data:image/png;base64,None".
+  it should "require b64_json to be a string before building a data URL" in {
+    val out = ImageTaskCodegen.parsePython(makeCtx())
+    out should include("""isinstance(b64, str)""")
+    out should not include 
("""f"data:image/png;base64,{data[0]['b64_json']}"""")
+  }
+
   it should "fall back to json.dumps(body) for structured tasks" in {
     val out = ImageTaskCodegen.parsePython(makeCtx())
     out should include("json.dumps(body)")

Reply via email to