Skip to content

fix(standalone-activities): decode failure encodedAttributes in activity detail#3507

Merged
Alex-Tideman merged 1 commit into
temporalio:mainfrom
edwardzhu0211:fix/standalone-activity-failure-codec-decode
Jun 9, 2026
Merged

fix(standalone-activities): decode failure encodedAttributes in activity detail#3507
Alex-Tideman merged 1 commit into
temporalio:mainfrom
edwardzhu0211:fix/standalone-activity-failure-codec-decode

Conversation

@edwardzhu0211

@edwardzhu0211 edwardzhu0211 commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Description & motivation 💭

On the Standalone Activity detail page, failures are rendered with a plain CodeBlock and JSON.stringify, which bypasses codec decoding entirely — in two places:

  • Result panel — outcome.failure (activity-input-and-outcome.svelte)
  • Last Failure panel — info.lastFailure (standalone-activity-details.svelte)

When the SDK's failure converter is configured with EncodeCommonAttributes, the error message and stack trace are stored in the failure's encodedAttributes payload. Because that payload is never sent to the codec server, both panels show raw, e.g.:

{
  "message": "Encoded failure",
  "source": "GoSDK",
  "encodedAttributes": {
    "metadata": { "encoding": "YmluYXJ5L3psaWI=" },
    "data": "eJziEuPiSM1Lzk/..."
  },
  "applicationFailureInfo": {}
}

The Input panel (and the successful Result panel) already use PayloadCodeBlock and decode correctly — so on the same page, input decodes but failures do not.

Fix

Render both failures with PayloadCodeBlock, the same component used for input/result. For a non-Payload/Payloads object it routes through decodeEventAttributes, which recursively decodes both payloads and encodedAttributes via the codec server — matching how the workflow event-history view already renders failures.

 // activity-input-and-outcome.svelte (Result panel)
 {#if has(outcome, 'failure')}
-  <CodeBlock content={JSON.stringify(outcome.failure, null, 2)} />
+  <PayloadCodeBlock value={outcome.failure} />

 // standalone-activity-details.svelte (Last Failure panel)
-<CodeBlock content={JSON.stringify($activityExecution.info.lastFailure, null, 2)} />
+<PayloadCodeBlock value={$activityExecution.info.lastFailure} />

Screenshots (if applicable) 📸

Before (current UI, no change applied — with a codec server configured): the failure encodedAttributes.data is shown as raw base64 in the Result and Last Failure panels.
Screenshot 2026-06-06 at 2 38 19 PM

After (with this change applied): encodedAttributes is decoded to { "message": "...", "stack_trace": "..." }, consistent with the decoded Input.
Screenshot 2026-06-06 at 2 38 28 PM

Testing 🧪

Verified end-to-end against a local stack: a Temporal SDK worker with a PayloadCodec data converter + failure converter (EncodeCommonAttributes: true), a failing Standalone Activity, a codec server, and the UI pointed at it. Both the Result and Last Failure panels render the decoded message/stack.

This is a Svelte template change (swapping in the same PayloadCodeBlock the Input/Result panels already use), and there's no component-render harness here to unit-test it directly, so it was verified manually + E2E.

  • full unit suite (pnpm test) -> green
  • pnpm check (svelte-check) -> 0 errors
  • Prettier + ESLint clean on changed files

Steps for others to test 🚶

  1. Run a Temporal SDK worker whose client sets a PayloadCodec data converter and a failure converter with EncodeCommonAttributes: true.
  2. Execute a Standalone Activity that fails.
  3. Point the UI at a codec server (--ui-codec-endpoint, or set it in the UI settings).
  4. Open the failed Standalone Activity detail page. The Result and Last Failure panels now show the decoded message/stack instead of raw encodedAttributes.

Docs

Any docs updates needed?

No.

@edwardzhu0211
edwardzhu0211 requested a review from a team as a code owner June 6, 2026 20:56
@vercel

vercel Bot commented Jun 6, 2026

Copy link
Copy Markdown

@edwardzhu0211 is attempting to deploy a commit to the Temporal Team on Vercel.

A member of the Team first needs to authorize it.

@CLAassistant

CLAassistant commented Jun 6, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@edwardzhu0211
edwardzhu0211 force-pushed the fix/standalone-activity-failure-codec-decode branch from ebcecf3 to d0c72a6 Compare June 6, 2026 21:32
@edwardzhu0211 edwardzhu0211 changed the title fix(standalone-activities): decode failure encodedAttributes in Result panel fix(standalone-activities): decode failure encodedAttributes in activity detail Jun 6, 2026
…ity detail

The Standalone Activity detail page rendered failures with a plain CodeBlock
and JSON.stringify, bypassing the codec entirely, in two places:

- the Result panel (activity-input-and-outcome.svelte) for `outcome.failure`
- the Last Failure panel (standalone-activity-details.svelte) for `info.lastFailure`

As a result a failure's `encodedAttributes` payload (where the SDK's failure
converter stores the error message and stack trace when configured with
EncodeCommonAttributes) was shown as raw base64 instead of being decoded — even
when a codec server was configured and the Input/Result decoded correctly.

Render both with PayloadCodeBlock, which routes the object through
decodeEventAttributes and recursively decodes both `payloads` and
`encodedAttributes` via the codec server — matching how the workflow
event-history view already renders failures, and completing the temporalio#3299 refactor
that moved Input/Result to PayloadCodeBlock but missed the failure branch.
@edwardzhu0211
edwardzhu0211 force-pushed the fix/standalone-activity-failure-codec-decode branch from d0c72a6 to 3e1de17 Compare June 6, 2026 22:15
@Alex-Tideman
Alex-Tideman requested a review from rossedfort June 8, 2026 13:51
@Alex-Tideman
Alex-Tideman merged commit d7e5eb4 into temporalio:main Jun 9, 2026
18 of 20 checks passed
laurakwhit added a commit that referenced this pull request Jun 23, 2026
Auto-generated version bump from 2.51.0 to 2.51.1

Specific version: 2.51.1

Changes included:
- [`c848ec54`](c848ec5) fix(a11y): announce workflow / event status on timeline graph nodes (WCAG 1.4.1) (#3443)
- [`af6b12a9`](af6b12a) fix(deployments): align version/status/compute badges in worker deployments table (#3489)
- [`df86587c`](df86587) Add SDK version to standalone activity details (#3447)
- [`59695290`](5969529) Use shared FilterBar component for workflows (#3448)
- [`ded94469`](ded9446) Set display contents in wrapper div if no afterLabel in Input component (#3513)
- [`d7e5eb43`](d7e5eb4) fix(standalone-activities): decode failure encodedAttributes in activity detail (#3507)
- [`81a255a9`](81a255a) fix(DT-4151): fix bottom nav scrollability and double-menu on mobile (#3514)
- [`368f646e`](368f646) Fix exports to work properly with vite8 (#3519)
- [`231bdaff`](231bdaf) chore(deps-dev): bump vitest from 3.2.4 to 3.2.6 (#3509)
- [`1de44ea6`](1de44ea) fix(workers): soften no-workers-polling alert for serverless worker deployments (#3524)
- [`689955a8`](689955a) fix(DT-4080): surface error when validate connection has no compute config, warn on set current (#3516)
- [`93323db9`](93323db) feat(DT-4078): Add Set Ramping Version to Worker Deployment Versions (#3508)
- [`9d3450c0`](9d3450c) fix(DT-4081): surface task queue not registered error in validate connection modal (#3517)
- [`b7f56237`](b7f5623) feat(DT-4079): miscellaneous WD UI fixes (#3511)
- [`83b2d4ec`](83b2d4e) feat(deployments): simplify create worker deployment UX (#3518)
- [`ccb4cb73`](ccb4cb7) Standalone Activity write guards (#3534)
- [`ab20ef03`](ab20ef0) Worker insights UI updates (#3520)
- [`aaf63bdc`](aaf63bd) [wcag] Replace text-[12px] with text-xs in DatePicker action buttons (SC 1.4.4) (#3525)
- [`743be902`](743be90) a11y(2.4.3): replace flex-wrap-reverse with flex-wrap on workflow history toolbar (#3527)
- [`41b73e87`](41b73e8) a11y(2.4.2): ui-main — set distinct, descriptive titles on login/signin, task-queues list, and activity-workers sub-tab (#3535)
- [`3d64cdbf`](3d64cdb) [WCAG 2.4.3] group-details-row — remove redundant outer focus stop on <g> wrapper (#3537)
- [`883e5db1`](883e5db) a11y(2.4.6): datepicker — replace empty label with translate('common.start') (#3543)
- [`9da915e2`](9da915e) a11y(2.4.5): import history — add back-link to Import landing page (#3542)
- [`ca4c1d61`](ca4c1d6) Cache new Intl.DateTimeFormat (#3565)
- [`38376e4d`](38376e4) Fix required activity timeout inputs on Start a Standalone Activity form (#3567)
- [`49d7c9e4`](49d7c9e) Use separate copy for title vs menu item (#3568)
- [`3c7dcdc3`](3c7dcdc) a11y(2.5.8): pagination — grow caret buttons from 12×12 to 24×24 CSS px (#3547)
- [`b5171825`](b517182) a11y(2.5.8): chip — pad remove button to 24×24 CSS px minimum (#3544)
- [`1fea5d5c`](1fea5d5) a11y(2.1.1): fake-button widgets — replace deprecated onkeypress with onkeydown handling Enter and Space (#3528)
- [`5bf09000`](5bf0900) a11y(2.1.1): navigation primitives — replace hover-only CSS :after label tooltip with focusable Tooltip (#3529)
- [`deed43f0`](deed43f) a11y(2.1.1): event summary row — add keyboard-accessible expand control alongside the mouse-only <tr onclick> (#3526)
- [`d401123e`](d401123) a11y(2.5.8): checkbox — add min-h-6 min-w-6 to Label for 24×24 hit area (#3545)
- [`aef4166f`](aef4166) [a11y] Expose toggled state via aria-pressed on ToggleButton (#3559)
- [`797f8831`](797f883) Show single attempt in Standalone Activity details (#3572)
- [`893bc58c`](893bc58) feat(DT-4183): Add Tabs (Primitive) (#3574)
- [`323c1993`](323c199) Date picker input field bug/kt (#3522)
- [`3ac34ce2`](3ac34ce) Various serverless UI updates (#3573)
- [`f365416a`](f365416) a11y(2.1.1): ZoomSvg — add keyboard pan/zoom controls so the workflow family tree is operable without a mouse (#3530)
- [`feb6897e`](feb6897) Fix gaps in slot cards on worker details page (#3580)
- [`b3c80072`](b3c8007) Remove font weight on cache size (#3583)
- [`0e7337ea`](0e7337e) Bump API to v1.62.14 (#3575)

Co-authored-by: laurakwhit <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants