Skip to content

Commit e2b077f

Browse files
authored
fix(conditional): don't error in condition blocks when no conditions are satisfied (#2243)
* fix(conditional): don't error in condition blocks when no conditions are satisfied * updated docs
1 parent d09fd6c commit e2b077f

File tree

3 files changed

+32
-13
lines changed

3 files changed

+32
-13
lines changed

apps/docs/content/docs/en/blocks/condition.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ Function (Process) → Condition (account_type === 'enterprise') → Advanced or
135135
## Best Practices
136136

137137
- **Order conditions correctly**: Place more specific conditions before general ones to ensure specific logic takes precedence over fallbacks
138-
- **Include a default condition**: Add a catch-all condition (`true`) as the last condition to handle unmatched cases and prevent workflow execution from getting stuck
138+
- **Use the else branch when needed**: If no conditions match and the else branch is not connected, the workflow branch will end gracefully. Connect the else branch if you need a fallback path for unmatched cases
139139
- **Keep expressions simple**: Use clear, straightforward boolean expressions for better readability and easier debugging
140140
- **Document your conditions**: Add descriptions to explain the purpose of each condition for better team collaboration and maintenance
141141
- **Test edge cases**: Verify conditions handle boundary values correctly by testing with values at the edges of your condition ranges

apps/sim/executor/handlers/condition/condition-handler.test.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ describe('ConditionBlockHandler', () => {
365365
)
366366
})
367367

368-
it('should throw error if no condition matches and no else exists', async () => {
368+
it('should return no-match result if no condition matches and no else exists', async () => {
369369
const conditions = [
370370
{ id: 'cond1', title: 'if', value: 'false' },
371371
{ id: 'cond2', title: 'else if', value: 'context.value === 99' },
@@ -392,9 +392,15 @@ describe('ConditionBlockHandler', () => {
392392
.mockReturnValueOnce('false')
393393
.mockReturnValueOnce('context.value === 99')
394394

395-
await expect(handler.execute(mockContext, mockBlock, inputs)).rejects.toThrow(
396-
`No matching path found for condition block "${mockBlock.metadata?.name}", and no 'else' block exists.`
397-
)
395+
const result = await handler.execute(mockContext, mockBlock, inputs)
396+
397+
// Should return success with no path selected (branch ends gracefully)
398+
expect((result as any).conditionResult).toBe(false)
399+
expect((result as any).selectedPath).toBeNull()
400+
expect((result as any).selectedConditionId).toBeNull()
401+
expect((result as any).selectedOption).toBeNull()
402+
// Decision should not be set when no condition matches
403+
expect(mockContext.decisions.condition.has(mockBlock.id)).toBe(false)
398404
})
399405

400406
it('falls back to else path when loop context data is unavailable', async () => {

apps/sim/executor/handlers/condition/condition-handler.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,17 @@ export class ConditionBlockHandler implements BlockHandler {
8787
block
8888
)
8989

90+
// Handle case where no condition matched and no else exists - branch ends gracefully
91+
if (!selectedConnection || !selectedCondition) {
92+
return {
93+
...((sourceOutput as any) || {}),
94+
conditionResult: false,
95+
selectedPath: null,
96+
selectedConditionId: null,
97+
selectedOption: null,
98+
}
99+
}
100+
90101
const targetBlock = ctx.workflow?.blocks.find((b) => b.id === selectedConnection?.target)
91102
if (!targetBlock) {
92103
throw new Error(`Target block ${selectedConnection?.target} not found`)
@@ -145,8 +156,8 @@ export class ConditionBlockHandler implements BlockHandler {
145156
ctx: ExecutionContext,
146157
block: SerializedBlock
147158
): Promise<{
148-
selectedConnection: { target: string; sourceHandle?: string }
149-
selectedCondition: { id: string; title: string; value: string }
159+
selectedConnection: { target: string; sourceHandle?: string } | null
160+
selectedCondition: { id: string; title: string; value: string } | null
150161
}> {
151162
for (const condition of conditions) {
152163
if (condition.title === CONDITION.ELSE_TITLE) {
@@ -185,14 +196,16 @@ export class ConditionBlockHandler implements BlockHandler {
185196
if (elseConnection) {
186197
return { selectedConnection: elseConnection, selectedCondition: elseCondition }
187198
}
188-
throw new Error(
189-
`No path found for condition block "${block.metadata?.name}", and 'else' connection missing.`
190-
)
199+
// Else exists but has no connection - treat as no match, branch ends
200+
logger.info(`No condition matched and else has no connection - branch ending`, {
201+
blockId: block.id,
202+
})
203+
return { selectedConnection: null, selectedCondition: null }
191204
}
192205

193-
throw new Error(
194-
`No matching path found for condition block "${block.metadata?.name}", and no 'else' block exists.`
195-
)
206+
// No condition matched and no else exists - branch ends gracefully
207+
logger.info(`No condition matched and no else block - branch ending`, { blockId: block.id })
208+
return { selectedConnection: null, selectedCondition: null }
196209
}
197210

198211
private findConnectionForCondition(

0 commit comments

Comments
 (0)