Skip to content

feat(logs): add retry from context menu and detail sidebar for failed runs#4181

Open
waleedlatif1 wants to merge 3 commits intostagingfrom
feat/retry-failed-log-v2
Open

feat(logs): add retry from context menu and detail sidebar for failed runs#4181
waleedlatif1 wants to merge 3 commits intostagingfrom
feat/retry-failed-log-v2

Conversation

@waleedlatif1
Copy link
Copy Markdown
Collaborator

Summary

  • Persist workflowInput in execution log data so it can be recovered for retry
  • Add "Retry" to the right-click context menu on failed log rows
  • Add retry button in the log detail sidebar header for failed runs
  • Add useRetryExecution mutation hook using streaming to avoid blocking on long workflows
  • Fall back to executionState.blockStates for old logs that don't have workflowInput

Type of Change

  • New feature

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Apr 15, 2026 6:43pm

Request Review

@cursor
Copy link
Copy Markdown

cursor bot commented Apr 15, 2026

PR Summary

Medium Risk
Adds a new workflow execution path from the logs UI and persists additional execution data (workflowInput) into stored logs, which could impact log payload size and retry correctness for legacy executions.

Overview
Enables retrying failed workflow executions directly from the logs UI via a new Retry action in the log row context menu and a retry button in the log details sidebar header (with pending/disabled states).

Adds a useRetryExecution mutation that POSTs to /api/workflows/{id}/execute using streaming and cancels after the first chunk to avoid blocking, and wires it into logs.tsx with toasts and a detail-log fetch to obtain the original input.

Persists executionData.workflowInput into execution logs (types + logger) and introduces extractRetryInput to prefer this field while falling back to reconstructing input from legacy executionState.blockStates.

Reviewed by Cursor Bugbot for commit 2591102. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 15, 2026

Greptile Summary

This PR adds a retry action for failed workflow runs via the log row context menu and the detail sidebar, persisting workflowInput at execution completion so the original payload can be recovered for retry. The useRetryExecution mutation uses a streaming trigger-and-cancel pattern to avoid blocking the UI on long-running workflows. The previous review concerns (fallback heuristic, isPending guard) have been addressed.

  • workflowInput stored without redaction (logger.ts lines 375–383): traceSpans and finalOutput are passed through redactApiKeys() before persisting, but workflowInput is not. Credentials embedded in webhook payloads, API-trigger bodies, or manual inputs will be stored in plaintext in the executionData column and surfaced to all log-view users.

Confidence Score: 4/5

Safe to merge after addressing the unredacted workflowInput storage — the UI and hook changes are clean and the previous review issues are resolved.

One P1 security finding: workflowInput bypasses redactApiKeys() while traceSpans and finalOutput are both redacted. All other findings are P2 or lower. Prior review concerns (fallback heuristic, isPending guard) are confirmed resolved.

apps/sim/lib/logs/execution/logger.ts — unredacted workflowInput persistence

Security Review

  • Unredacted credential storage (lib/logs/execution/logger.ts): workflowInput is written to the executionData JSON column without passing through redactApiKeys(). Webhook payloads, API-trigger bodies, and manual inputs containing tokens, passwords, or API keys are stored in plaintext and returned to any user with log-view access. traceSpans and finalOutput receive the same redactApiKeys() treatment, so this field is inconsistently protected.

Important Files Changed

Filename Overview
apps/sim/lib/logs/execution/logger.ts Persists workflowInput to the database without passing it through redactApiKeys(), while traceSpans and finalOutput are redacted. Also uses any for workflowInput parameter type.
apps/sim/hooks/queries/logs.ts Adds useRetryExecution mutation that fires POST /execute with stream: true, reads one chunk, then cancels to trigger server-side execution without blocking; cache invalidation and isPending guard are correct.
apps/sim/app/workspace/[workspaceId]/logs/utils.ts Adds extractRetryInput with correct fallback heuristic (executed === false && executionTime === 0) for old logs; logic is clean and the previous reviewer concerns are addressed.
apps/sim/app/workspace/[workspaceId]/logs/logs.tsx Wires retry logic through retryLog, passes isRetryPending to both LogRowContextMenu and LogDetails; useCallback deps are correctly suppressed per project guidelines for stable TanStack Query refs.
apps/sim/app/workspace/[workspaceId]/logs/components/log-row-context-menu/log-row-context-menu.tsx Context menu correctly gates the Retry item behind isRetryable and disables it while isRetryPending; shows "Retrying…" label during in-flight mutation.
apps/sim/app/workspace/[workspaceId]/logs/components/log-details/log-details.tsx Retry button added to sidebar header, correctly gated on log.status === 'failed' and disabled while isRetryPending.
apps/sim/lib/logs/types.ts Adds workflowInput?: unknown to WorkflowExecutionLog.executionData — correctly typed; aligns with completeWorkflowExecution interface update.

Sequence Diagram

sequenceDiagram
    participant U as User
    participant CM as ContextMenu / Sidebar
    participant RL as retryLog()
    participant QC as QueryClient
    participant RE as useRetryExecution
    participant API as /api/workflows/:id/execute

    U->>CM: Right-click failed log / click Retry
    CM->>RL: retryLog(log)
    RL->>QC: fetchQuery(logKeys.detail(logId))
    QC->>API: GET /api/logs/:logId
    API-->>QC: WorkflowLog (with workflowInput)
    QC-->>RL: detailLog
    RL->>RL: extractRetryInput(detailLog)
    note over RL: prefers workflowInput field,<br/>falls back to blockStates heuristic
    RL->>RE: mutateAsync({ workflowId, input })
    RE->>API: POST /execute {input, triggerType:"manual", stream:true}
    API-->>RE: stream (first chunk)
    RE->>RE: reader.read() then reader.cancel()
    note over RE: execution continues server-side
    RE-->>RL: { started: true }
    RL-->>U: toast.success("Retry started")
    RE->>QC: invalidate logs + details + stats
Loading

Comments Outside Diff (1)

  1. apps/sim/lib/logs/execution/logger.ts, line 375-384 (link)

    P1 security workflowInput persisted without API-key redaction

    traceSpans and finalOutput both pass through redactApiKeys() before reaching buildCompletedExecutionData, but workflowInput is forwarded as-is. Any credentials embedded in a workflow's input — OAuth tokens from webhook payloads, API keys passed via the API trigger, passwords in manual inputs — will be stored in plaintext in the executionData JSON column and surfaced through the log detail endpoint to all users with log-view access.

    Since the unredacted value is needed for retry fidelity, one option is to store two fields: workflowInput (redacted, for display) and workflowInputRaw (encrypted or access-controlled, for retry only). Alternatively, if raw storage is intentional, the log-detail API response should explicitly filter workflowInput before sending it to clients, and this should be documented.

Reviews (3): Last reviewed commit: "fix(logs): store workflowInput unredacte..." | Re-trigger Greptile

Comment thread apps/sim/app/workspace/[workspaceId]/logs/utils.ts
Comment thread apps/sim/app/workspace/[workspaceId]/logs/logs.tsx
Comment thread apps/sim/app/workspace/[workspaceId]/logs/utils.ts
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/lib/logs/execution/logger.ts Outdated
workflowInput is internal execution data used for replay, same as
executionState which is also stored unredacted. Redacting at storage
time corrupts the data for retry use cases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 2591102. Configure here.

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.

1 participant