Skip to content

Conversation

@waleedlatif1
Copy link
Collaborator

@waleedlatif1 waleedlatif1 commented Jan 28, 2026

Summary

Fixes timeout configuration not being honored for API blocks and adds proper validation.

Changes

1. Internal Routes Timeout Support (apps/sim/tools/index.ts)

  • Added AbortController to support timeouts for internal routes (/api/*)
  • Previously only external URLs honored the timeout setting
  • Internal routes now use same 5-minute default as external routes

2. Type Coercion Fix (apps/sim/tools/utils.ts)

  • The short-input subBlock returns a string but code expected a number
  • Now properly converts using Number() with validation

3. Timeout Validation (apps/sim/tools/utils.ts)

  • Validates timeout is a finite positive number
  • Rejects negative values, zero, Infinity, and NaN
  • Enforces max timeout of 600000ms (10 minutes) as documented

4. Consistent Error Messages (apps/sim/lib/core/security/input-validation.ts)

  • External routes now report actual timeout value in error message
  • Both internal and external routes use consistent format: Request timed out after Xms

5. Cleanup (apps/sim/tools/index.ts)

  • Removed redundant clearTimeout in catch block (finally always executes)

Test Plan

  • TypeScript compiles without errors
  • Lint passes
  • Core tools tests pass
  • Manual test: API block with custom timeout on external URL
  • Manual test: API block with custom timeout on internal route
  • Manual test: Timeout exceeding 600000ms gets clamped

Fixes #2786
Fixes #2242

@vercel
Copy link

vercel bot commented Jan 28, 2026

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

1 Skipped Deployment
Project Deployment Review Updated (UTC)
docs Skipped Skipped Jan 29, 2026 1:13am

Request Review

…oercion

- Add AbortController support for internal routes (/api/*) to honor timeout
- Fix type coercion: convert string timeout from short-input to number
- Handle NaN gracefully by falling back to undefined (default timeout)

Fixes #2786
Fixes #2242
@waleedlatif1 waleedlatif1 changed the base branch from main to staging January 28, 2026 22:01
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 28, 2026

Greptile Overview

Greptile Summary

This PR fixes timeout configuration for API blocks by adding support for internal routes and fixing type coercion issues.

Key Changes:

  • Added AbortController to support timeout for internal routes (/api/*) which previously ignored the timeout parameter
  • Fixed type coercion bug where string timeout values from UI weren't converted to numbers (the as number cast didn't actually convert)
  • Added validation to ensure timeout is positive (negative values would cause immediate abort in JavaScript)
  • Added timeout subBlock to API block UI for user configuration

Additional Changes:

  • Search modal refactoring (unrelated to timeout feature) - removed description and keywords fields, improved filter performance
  • These changes appear to be performance optimizations bundled in the same commit

The timeout implementation correctly handles both internal and external routes, with proper error handling and cleanup.

Confidence Score: 5/5

  • Safe to merge - fixes critical timeout bugs with proper validation and error handling
  • The timeout implementation is clean and follows best practices. Type coercion fix prevents runtime errors. AbortController pattern is correctly implemented with proper cleanup in finally block. No security issues or breaking changes.
  • No files require special attention

Important Files Changed

Filename Overview
apps/sim/tools/index.ts Added AbortController timeout support for internal routes, matching external route behavior
apps/sim/tools/utils.ts Fixed type coercion for timeout param and added validation for positive numbers
apps/sim/blocks/blocks/api.ts Added timeout subBlock UI configuration with proper description
apps/sim/tools/http/types.ts Added timeout field to RequestParams interface

Sequence Diagram

sequenceDiagram
    participant UI as API Block UI
    participant Block as api.ts
    participant Utils as tools/utils.ts
    participant Index as tools/index.ts
    participant Fetch as fetch/secureFetch

    UI->>Block: User sets timeout (string)
    Block->>Utils: formatRequestParams(tool, params)
    Note over Utils: Convert string to number<br/>Validate timeout > 0
    Utils->>Index: executeToolRequest(requestParams)
    
    alt Internal Route (/api/*)
        Note over Index: Create AbortController
        Index->>Index: setTimeout(timeout || 300000)
        Index->>Fetch: fetch(url, { signal })
        alt Timeout occurs
            Index->>Index: controller.abort()
            Fetch-->>Index: AbortError
            Index-->>Block: Error: "Request timed out after Xms"
        else Success
            Fetch-->>Index: Response
            Index->>Index: clearTimeout()
            Index-->>Block: Response data
        end
    else External URL
        Index->>Fetch: secureFetchWithPinnedIP(url, { timeout })
        Note over Fetch: Native timeout support<br/>via requestOptions.timeout
        alt Timeout occurs
            Fetch-->>Index: Timeout error
            Index-->>Block: Error
        else Success
            Fetch-->>Index: Response
            Index-->>Block: Response data
        end
    end
Loading

@waleedlatif1 waleedlatif1 changed the title fix(timeout): honor API block timeout configuration fix(timeout): add API block timeout configuration Jan 28, 2026
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

5 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@waleedlatif1 waleedlatif1 changed the title fix(timeout): add API block timeout configuration feat(timeout): add API block timeout configuration Jan 28, 2026
Negative timeout values would cause immediate request abort since
JavaScript treats negative setTimeout delays as 0.
@waleedlatif1
Copy link
Collaborator Author

@greptile

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

3 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

@waleedlatif1
Copy link
Collaborator Author

@greptile

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

4 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

- Internal routes now use same 5-minute default as external routes
- Added Number.isFinite() check to reject Infinity values
@waleedlatif1
Copy link
Collaborator Author

@greptile

- Clamp timeout to max 600000ms (10 minutes) as documented
- External routes now report timeout value in error message
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

4 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

@waleedlatif1 waleedlatif1 merged commit 06d7ce7 into staging Jan 29, 2026
7 checks passed
@waleedlatif1 waleedlatif1 deleted the fix/timeout branch January 29, 2026 01:14
Copy link

@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.

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

? Math.min(timeout, MAX_TIMEOUT_MS)
: undefined

return { url, method, headers, body, timeout: validTimeout }
Copy link

Choose a reason for hiding this comment

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

Timeout parameter incorrectly applied to all tools

Medium Severity

The new timeout handling in formatRequestParams extracts params.timeout for ALL tools and uses it as the HTTP request timeout. However, tools like firecrawl, apify, and elasticsearch have their own timeout parameter that serves a different purpose—it's an API-level parameter (e.g., how long firecrawl should spend scraping), not an HTTP request timeout. When a user sets timeout=60000 for firecrawl intending 60 seconds of scrape time, the HTTP request will now also abort after 60 seconds, potentially failing before the API completes its work and returns a response.

Additional Locations (1)

Fix in Cursor Fix in Web

})
// Set up AbortController for timeout support on internal routes
const controller = new AbortController()
const timeout = requestParams.timeout || 300000
Copy link

Choose a reason for hiding this comment

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

Duplicated magic number for default timeout value

Low Severity

The magic number 300000 (5 minute timeout) is duplicated in two locations added by this PR. The codebase already has centralized timeout constants like A2A_DEFAULT_TIMEOUT in lib/a2a/constants.ts and CHAT_REQUEST_TIMEOUT_MS in app/chat/constants.ts with the same value. A shared constant like DEFAULT_REQUEST_TIMEOUT_MS would ensure consistency and make future changes easier to manage across the codebase.

Additional Locations (1)

Fix in Cursor Fix in Web

nativeInputValueSetter.call(inputRef.current, '')
inputRef.current.dispatchEvent(new Event('input', { bubbles: true }))
}
inputRef.current.focus()
Copy link

Choose a reason for hiding this comment

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

Overly complex DOM manipulation to clear input

Low Severity

The new approach uses Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value')?.set to clear the search input, which is more complex than the previous controlled React state pattern (setSearch('')). This DOM manipulation technique relies on browser implementation details and is harder to understand and maintain than standard React state management.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants