Skip to content

Conversation

@michaelmalave
Copy link
Contributor

@michaelmalave michaelmalave commented Oct 16, 2025

Summary

Fixed silent failure issue in heroku run:inside and improved error messages in heroku logs when executed outside trusted IP ranges. Added uniform error handling for 403 HTTP responses to provide clear error messages instead of silent failures or generic errors.

Type of Change

  • fix: Bug fix or issue (patch semvar update)
  • feat: Introduces a new feature to the codebase (minor semvar update)
  • perf: Performance improvement
  • docs: Documentation only changes
  • tests: Adding missing tests or correcting existing tests
  • chore: Code cleanup tasks, dependency updates, or other changes

Note: Add a ! after your change type to denote a breaking change.

Testing

yarn && yarn build

Follow guide for staging heroku environment here: staging setup.

get current webserver

heroku ps -a michael-test-fir-app

Confirm ip restrictions (should be empty). Use the remove command if needed:

./bin/run spaces:trusted-ips --space michael-test-fir-space

./bin/run spaces:trusted-ips:remove [range] --space michael-test-fir-space

Run commands against test space + app with IP restrictions enabled:

./bin/run run:inside <webserver> -a michael-test-fir-app ls

./bin/run logs -a michael-test-fir-app --tail

Both should return the same error: Error: You can't access this space from your IP address. Contact your team admin.

Additional Context

  • Root Cause:

    • The run:inside command failed silently when IP restrictions were active because the HTTPS request in the SSH connection path received a 403 response but had no handler for it, causing the Promise to hang indefinitely waiting for an upgrade event that never came.
    • The logs command displayed generic error messages for 403 responses because EventSource doesn't expose HTTP response bodies, making it impossible to distinguish between IP restrictions (immediate 403) and stream expiration errors (delayed 403 after messages were received).
  • Fix Applied:

    • dyno.ts: Added HTTP response handler in _connect() method to check for 403 status codes before the upgrade event and reject the Promise with a user-friendly error message: "You can't access this space from your IP address. Contact your team admin."
    • log-displayer.ts: Implemented connection state tracking using a hasReceivedMessages flag to distinguish between immediate 403 errors (IP restrictions) and delayed 403 errors (stream expiration). The error handler now:
      • Tracks whether any log messages were received before the 403 error using hasReceivedMessages flag
      • For immediate 403 (no messages received): Shows "You can't access this space from your IP address. Contact your team admin."
      • For delayed 403 (messages were received): Shows "Log stream access expired. Please try again."
      • For 404 with tail enabled: Shows "Log stream access expired. Please try again." for consistency
  • Implementation Details:

    • Used connection state tracking instead of fetching response bodies (which EventSource doesn't expose)
    • Added hasReceivedMessages boolean flag that is set to true when the first message event is received
    • The error handler checks this flag to determine if the 403 occurred immediately (IP restriction) or after receiving messages (stream expiration)
    • This approach works around EventSource's limitation of not exposing response bodies in error events

Resolved usage:
image

Related Issue

Closes @W-20247783@

…ands. Prevents silent failures when commands are executed outside trusted IP ranges
@michaelmalave michaelmalave requested a review from a team as a code owner October 16, 2025 23:03
@michaelmalave michaelmalave changed the title chore: add IP restriction error handling for run:inside and logs commands feat: add IP restriction error handling for run:inside and logs commands Oct 22, 2025
@michaelmalave michaelmalave changed the title feat: add IP restriction error handling for run:inside and logs commands fix: ensure IP restriction error handling for run:inside and logs commands Oct 22, 2025
@michaelmalave michaelmalave marked this pull request as draft November 18, 2025 16:56
@michaelmalave michaelmalave marked this pull request as ready for review November 20, 2025 23:39
Copy link
Contributor

@tlowrimore-heroku tlowrimore-heroku left a comment

Choose a reason for hiding this comment

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

Nice! This looks great! I really like the AbortController-based clean-up logic.

@michaelmalave michaelmalave merged commit 42b3a2a into main Nov 21, 2025
8 checks passed
@michaelmalave michaelmalave deleted the mm/chore/uniform-errors-outside-trusted-ips branch November 21, 2025 16:50
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.

3 participants