Open TranquilMarmot opened 10 months ago
➤ Automation for Jira commented:
The link to the corresponding Jira issue is https://ably.atlassian.net/browse/SDK-4019
It seems like this error might be only caused in React dev mode since it calls hooks twice. Still curious about why we can't catch the error 🤔
Hey again @TranquilMarmot,
Apologies for the confusion here - the reason try catch isn't working is because client.close
isn't actually throwing the exception. The "Connection closed" error is a generic error we throw when you call certain realtime methods on a closed client (for example, if you try to attach to a channel when the connection is closed it will throw a "Connection closed" error). Currently this error is created when the connection is closed and a reference to the error stored for use later, but since javascript error stack traces point to where the Error
was constructed, this means that the stack trace will point to where you called client.close
in your app, rather than where the error was actually thrown. I realise that this is quite rubbish for dev-experience so I've created https://github.com/ably/ably-js/issues/1573 to amend this behaviour.
For now, until we've fixed that issue, I think you probably would have to manually debug where the error is being thrown from I'm afraid. From the looks of it, it would seem to me that in react strict mode your useAblyRealtimeClient
cleanup function would execute twice since strict mode will immediately unmount and re-mount any component which uses it, so this would result in the connection being closed immediately.
Error occurs inside a Promise, as seen in the stack trace you provided "Uncaught (in promise) Error:"
Does that mean that the error is happening inside of a promise in RealtimeBase.close():
? It seems like there's no way for us to catch it outside of the library.
It would be nice if close
returned a Promise
that we could await
so that we know when it's actually closed.
I think we may have gotten around this by tracking when we've already closed the connection in the hook:
export const useAblyRealtimeClient = (authParams?: Record<string, string>) => {
const clientRef = useRef<Realtime | null>(null);
const hasClosed = useRef(false);
useEffect(() => {
// don't create the ably client on the server because it will cause errors
if (typeof window !== "undefined") {
clientRef.current = createAblyRealtimeClient(authParams);
hasClosed.current = false;
}
return () => {
if (
!hasClosed.current &&
clientRef.current &&
["initialized", "connected", "connecting"].includes(
clientRef.current?.connection.state,
)
) {
clientRef.current?.close();
hasClosed.current = true;
}
clientRef.current = null;
};
}, [authParams?.chatId]);
return clientRef.current;
};
I have the same issue only in dev mode, no such error on stage
@VeskeR @owenpearson I also noticed that this error occurs after unmout in ablyClient
close method. During the call of this method the error Error: Connection closed
appears.
const [ablyClient, setAblyClient] = useState<Realtime | undefined>(undefined);
const [ablyChannel, setAblyChannel] = useState<RealtimeChannel | undefined>(
undefined
);
const destroyAbly = () => {
setAblyError(undefined);
if (ablyChannel) {
ablyChannel.off();
setAblyChannel(undefined);
}
if (ablyClient) {
ablyClient.close(); // Here error after call close
setAblyClient(undefined);
}
setAblyConnected(false);
};
Example of how destroyAbly
is used during unmount
const destoryRef = useRef(destroyAbly);
useEffect(() => {
destoryRef.current = destroyAbly;
}, [destroyAbly]);
useEffect(() => {
return () => {
destoryRef.current?.();
};
}, []);
I am using the latest version of ably - 2.0.3
In our Next.js app, we're creating / closing an Ably realtime client inside of a
useEffect
.This client is then passed as a prop to an
AblyProvider
.However, this still causes the Ably client to throw an error. Next.js will show us this:
More of a stack trace...
Some questions...
What status are we supposed to check for when closing the connection? If I log
clientRef.current?.connection.state
before we callclientRef.current?.close();
it's shown asconnecting
orconnected
.Why can't we
catch
this error? Even with theclose()
call inside of atry
/catch
, it isn't being caught (maybe this is an issue inside Next.js?)┆Issue is synchronized with this Jira Bug by Unito