From 42e842711a200f57f5530b781fccad1319261650 Mon Sep 17 00:00:00 2001 From: Shawn Garello Date: Tue, 20 Oct 2026 11:04:45 -0700 Subject: [PATCH 1/2] test(amber): reproduce the 500 from retrievePublicWorkflow --- .../resource/dashboard/file/WorkflowResourceSpec.scala | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/amber/src/test/scala/org/apache/texera/web/resource/dashboard/file/WorkflowResourceSpec.scala b/amber/src/test/scala/org/apache/texera/web/resource/dashboard/file/WorkflowResourceSpec.scala index 24cbf8da2aa..57616afc72a 100644 --- a/amber/src/test/scala/org/apache/texera/web/resource/dashboard/file/WorkflowResourceSpec.scala +++ b/amber/src/test/scala/org/apache/texera/web/resource/dashboard/file/WorkflowResourceSpec.scala @@ -1006,6 +1006,16 @@ class WorkflowResourceSpec assertThrows[ForbiddenException](workflowResource.makePublic(wid, sessionUser2)) } + "WorkflowResource.retrievePublicWorkflow" should "throw NotFoundException for a private workflow" in { + val wid = seedWorkflow(sessionUser1, "public-private-wf").workflow.getWid + assertThrows[NotFoundException](workflowResource.retrievePublicWorkflow(wid)) + } + + it should "throw NotFoundException for a wid that does not exist" in { + val wid = seedWorkflow(sessionUser1, "public-missing-wf").workflow.getWid + assertThrows[NotFoundException](workflowResource.retrievePublicWorkflow(wid + 100000)) + } + "WorkflowResource.duplicateWorkflow" should "create a distinct copy owned by the user" in { // duplicateWorkflow reassigns operator ids, so the content must have an operators array. val wid = seedWorkflow( From 75da5e998be1852de93ecf86646b6b65d8a0fe58 Mon Sep 17 00:00:00 2001 From: Shawn Garello Date: Tue, 20 Oct 2026 11:14:34 -0700 Subject: [PATCH 2/2] fix(amber): return 404 for unavailable public workflow retrievePublicWorkflow dereferenced the row from fetchOne() without a null check, so a wid that does not exist or names a private workflow answered 500 with a NullPointerException. It now throws NotFoundException (404), the same guard getWorkflowType already has. Closes #8139 Generated-by: Claude Code (Opus 5.5) --- .../resource/dashboard/user/workflow/WorkflowResource.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/amber/src/main/scala/org/apache/texera/web/resource/dashboard/user/workflow/WorkflowResource.scala b/amber/src/main/scala/org/apache/texera/web/resource/dashboard/user/workflow/WorkflowResource.scala index 6fbd19bcc2c..28d232c867e 100644 --- a/amber/src/main/scala/org/apache/texera/web/resource/dashboard/user/workflow/WorkflowResource.scala +++ b/amber/src/main/scala/org/apache/texera/web/resource/dashboard/user/workflow/WorkflowResource.scala @@ -959,6 +959,9 @@ class WorkflowResource extends LazyLogging { .where(WORKFLOW.WID.eq(wid)) .and(WORKFLOW.IS_PUBLIC.isTrue) .fetchOne() + if (workflow == null) { + throw new NotFoundException(s"Public workflow with id $wid not found") + } // Name and description come from the public copy for the same reason as the content: a pin has // to hold everything on show. val publicCopy = WorkflowPublishService.publicCopyOf(workflow.into(classOf[Workflow]))