Skip to content

fix(serializer): preserve block enabled state during deserialization#3950

Open
lawrence3699 wants to merge 1 commit intosimstudioai:mainfrom
lawrence3699:fix/deserializer-preserve-block-enabled-state
Open

fix(serializer): preserve block enabled state during deserialization#3950
lawrence3699 wants to merge 1 commit intosimstudioai:mainfrom
lawrence3699:fix/deserializer-preserve-block-enabled-state

Conversation

@lawrence3699
Copy link
Copy Markdown

Summary

The deserializer hardcodes enabled: true for regular blocks (line 625), ignoring the enabled field that was correctly saved during serialization (line 294). This causes disabled blocks to silently become re-enabled when a workflow is loaded, imported, or round-tripped through serialize/deserialize.

The loop/parallel branch at line 594 already handles this correctly with serializedBlock.enabled ?? true. This PR applies the same pattern to regular blocks.

Reproduction

  1. Create a workflow with multiple blocks
  2. Disable one of the blocks
  3. Save and reload the workflow (or import/export it)
  4. The disabled block is now enabled again

Fix

Change enabled: trueenabled: serializedBlock.enabled ?? true to match the pattern already used for loop/parallel blocks.

Test plan

  • Existing serializer tests continue to pass
  • Verify that disabling a block and reloading the workflow preserves the disabled state
  • Verify that workflows without an enabled field in serialized blocks default to true (backwards compatible)

The deserializer hardcodes `enabled: true` for regular blocks,
ignoring the `enabled` field that was correctly saved during
serialization. This causes disabled blocks to silently become
re-enabled when a workflow is loaded, imported, or round-tripped
through serialize/deserialize.

The loop/parallel branch already handles this correctly with
`serializedBlock.enabled ?? true` — apply the same pattern to
regular blocks.
Copilot AI review requested due to automatic review settings April 4, 2026 22:52
@cursor
Copy link
Copy Markdown

cursor bot commented Apr 4, 2026

PR Summary

Low Risk
Low risk: a one-line deserialization change that only affects whether blocks load as disabled vs enabled, with a safe default for older serialized workflows.

Overview
Fixes workflow deserialization to preserve each block’s enabled state instead of always re-enabling blocks.

Regular blocks now use enabled: serializedBlock.enabled ?? true, matching the existing loop/parallel handling and remaining backward-compatible when older serialized data omits enabled.

Reviewed by Cursor Bugbot for commit 5035869. Bugbot is set up for automated code reviews on this repo. Configure here.

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 4, 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 4, 2026 10:52pm

Request Review

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes workflow deserialization to preserve a block’s saved enabled state instead of re-enabling regular blocks unconditionally, preventing disabled blocks from silently becoming enabled after reload/import/round-trip.

Changes:

  • Update regular block deserialization to use serializedBlock.enabled ?? true, matching the existing loop/parallel behavior.
  • Maintain backward-compatible defaulting to true when enabled is absent.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 622 to 626
position: serializedBlock.position,
subBlocks,
outputs: serializedBlock.outputs,
enabled: true,
enabled: serializedBlock.enabled ?? true,
triggerMode:
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

This change will require updating the existing unit test that currently asserts the buggy behavior. apps/sim/serializer/tests/serializer.extended.test.ts has a case (should deserialize enabled status correctly) where enabled: false is expected to deserialize to true; after preserving enabled, it should assert false (and ideally add a separate assertion for the backward-compat default when enabled is missing).

Copilot uses AI. Check for mistakes.
Comment on lines 624 to 626
outputs: serializedBlock.outputs,
enabled: true,
enabled: serializedBlock.enabled ?? true,
triggerMode:
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

SerializedBlock.enabled is currently typed as a required boolean (apps/sim/serializer/types.ts), but deserialization now treats it as optional via serializedBlock.enabled ?? true for backward compatibility. Consider updating the SerializedBlock type (or introducing a versioned/migrated type) so the TypeScript types match the actual data shape coming from persisted workflows.

Copilot uses AI. Check for mistakes.
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 4, 2026

Greptile Summary

This PR fixes a silent state-loss bug in the workflow deserializer where regular blocks always came back as enabled: true regardless of their saved state, causing disabled blocks to be silently re-enabled on every workflow load, import, or round-trip.

  • Root cause: deserializeBlock (line 625) hardcoded enabled: true for all non-loop/parallel blocks, while the serializer (line 294) correctly saved block.enabled.
  • Fix: Replaces enabled: true with enabled: serializedBlock.enabled ?? true, identical to the pattern already used for loop/parallel blocks at line 594.
  • Backwards compatibility: The ?? true fallback ensures older serialized workflows without an enabled field default to true, preserving existing behaviour.
  • Test coverage: No existing automated test exercises deserialization of a disabled regular block; a regression test would strengthen the fix (see inline comment).

Confidence Score: 5/5

Safe to merge — the one-line fix is unambiguously correct and carries no regression risk.

The change mirrors the exact pattern already in use for loop/parallel blocks at line 594, the serialization side (line 294) already persists the field, and the ?? true default preserves backwards compatibility. The only finding is a P2 suggestion to add a regression test, which does not block merge.

No files require special attention; the single changed line in apps/sim/serializer/index.ts is straightforward.

Important Files Changed

Filename Overview
apps/sim/serializer/index.ts One-line fix: replaces hardcoded enabled: true with serializedBlock.enabled ?? true at line 625, preserving disabled block state during deserialization and matching the existing loop/parallel pattern at line 594

Sequence Diagram

sequenceDiagram
    participant UI as Workflow UI
    participant S as Serializer

    Note over UI,S: Save / Export
    UI->>S: serializeWorkflow(blocks)
    S-->>UI: SerializedBlock { enabled: false }

    Note over UI,S: Load / Import — Before Fix
    UI->>S: deserializeWorkflow(serialized)
    S-->>UI: BlockState { enabled: true } ❌ hardcoded

    Note over UI,S: Load / Import — After Fix
    UI->>S: deserializeWorkflow(serialized)
    S->>S: serializedBlock.enabled ?? true
    S-->>UI: BlockState { enabled: false } ✅ preserved
Loading

Comments Outside Diff (1)

  1. apps/sim/serializer/index.test.ts, line 248-249 (link)

    P2 Missing regression test for disabled block round-trip

    The PR's own test plan calls out "Verify that disabling a block and reloading the workflow preserves the disabled state", but no automated test covers this path. All existing deserializeWorkflow tests create blocks with enabled: true, so the bug fixed by this PR would not have been caught by the current suite.

    Consider adding a test inside the deserializeWorkflow describe block:

    it.concurrent('should preserve disabled state of a regular block through deserialization', () => {
      const { blocks, edges, loops } = createComplexWorkflowState()
      // Disable a regular block before serializing
      blocks.function1 = { ...blocks.function1, enabled: false }
      const serializer = new Serializer()
    
      const serialized = serializer.serializeWorkflow(blocks, edges, loops)
      const deserialized = serializer.deserializeWorkflow(serialized)
    
      expect(deserialized.blocks.function1.enabled).toBe(false)
      // Enabled blocks should remain enabled
      expect(deserialized.blocks.api1.enabled).toBe(true)
    })

    This would serve as a regression guard for the bug fixed here and satisfy the manual verification step in the test plan.

Reviews (1): Last reviewed commit: "fix(serializer): preserve block enabled ..." | Re-trigger Greptile

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.

2 participants