← Notes
June 16, 2026·2 min readopen-sourcecontributingdev

React Native OAuth Login Broken by AbortSignal.timeout: A Cross-Platform Compatibility Fix

React Native OAuth Login Broken by AbortSignal.timeout: A Cross-Platform Compatibility Fix

The oauth-client package relied on AbortSignal.timeout, a modern Web API unavailable in React Native, causing login flows to crash with TypeError. This fix adds a compatibility layer that detects the capability and falls back to manual timeout handling.

What

The oauth-client was calling AbortSignal.timeout at two call sites to enforce request timeouts. React Native and Expo do not implement this static method, so the code threw 'TypeError: AbortSignal.timeout is not a function' and broke OAuth login. The fix introduces a timeoutSignal() helper in util.ts that checks for native support and falls back to AbortController plus setTimeout, emitting a TimeoutError DOMException (or Error on older platforms) when the timeout fires.

Why it matters

This is a regression introduced in version 0.5.7. Assuming all JavaScript runtimes support modern Web APIs leads to silent failures in constrained environments like React Native. By detecting capabilities at runtime rather than at build time, the library remains compatible across Web, Node.js, and mobile runtimes without forking the codebase.

Who it's for

Any developer using the atproto oauth-client in a React Native or Expo application. The fix is transparent to end users but restores login functionality for mobile developers who depend on this library.

When & where

The issue was discovered after 0.5.7 shipped and is being addressed in a draft PR (#5101) against the bluesky-social/atproto repository. The fix applies to the oauth-client package, a shared dependency for OAuth integration across the atproto ecosystem.

How

A new timeoutSignal() helper was added to util.ts that wraps AbortSignal.timeout with a try-catch. If the method exists, it uses it directly. If not, it creates an AbortController and schedules a setTimeout to abort after the specified delay. The package adopted vitest for testing both the native path and the React Native fallback path, ensuring both code paths are exercised and verified.

Takeaway

Cross-platform JavaScript libraries should detect capabilities at runtime rather than assume Web API availability. A small compatibility layer and test coverage for both happy and fallback paths prevent regressions and keep the library usable across diverse JavaScript runtimes. This pattern is especially important for authentication flows where failures are user-facing.

Draft PR: https://github.com/bluesky-social/atproto/pull/5101

Building an AI agent?

I'm packaging how I ship them into one kit. Early access:

AI Agent Starter Kit →