
Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag storeI appreciate you sharing this issue, but I need to be upfront: I can't find useListeningQuery() in any official Sanity documentation. This appears to be from a third-party package that I can't verify as currently maintained or compatible with Sanity Studio 3.8.3.
Since I can't diagnose the specific errors you're seeing with an unverified hook, let me show you the official Sanity approach for handling real-time data in custom input components.
According to the Listening API documentation, Sanity provides a built-in real-time event streaming API using Server-Sent Events. Combined with the useClient hook, you can build a proper listening query with full control over error handling:
import { useClient } from 'sanity';
import { useEffect, useState } from 'react';
import { Card, Spinner, Stack, Text } from '@sanity/ui';
export function MyCustomInput(props) {
const client = useClient({ apiVersion: '2024-01-01' });
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
const { documentId } = props; // or however you're getting the ID
useEffect(() => {
let subscription;
try {
// Create a listening query
subscription = client
.listen(`*[_id == $documentId]`, { documentId })
.subscribe({
next: (update) => {
setData(update.result);
setLoading(false);
setError(null);
},
error: (err) => {
console.error('Listening error:', err);
setError(err);
setLoading(false);
// Connection will automatically retry
}
});
} catch (err) {
setError(err);
setLoading(false);
}
// Critical: cleanup on unmount
return () => {
if (subscription) {
subscription.unsubscribe();
}
};
}, [documentId, client]);
if (loading) return <Spinner />;
if (error) {
return (
<Card tone="critical" padding={3}>
<Stack space={2}>
<Text weight="semibold">Connection issue</Text>
<Text size={1}>
Unable to establish real-time connection.
{data && ' Showing last known data.'}
</Text>
</Stack>
</Card>
);
}
// Your main component logic
return (
<div>
{/* Your UI using data */}
</div>
);
}This approach gives you:
unsubscribe() call in the cleanup function prevents memory leaks and stream errorsThe errors you're seeing ("invalid object where a stream was expected" and "Could not establish EventSource connection") typically happen when:
The solution above avoids these issues by keeping the component mounted and using the proper cleanup pattern.
One more thing to consider: if you're querying the current document that your input component is part of, you probably don't need to fetch it separately. Custom input components automatically receive the document data through props - check the custom input components guide to see if the data you need is already available via props.value or other provided props.
If you can share more about what data you're trying to access and why, I might be able to suggest an even simpler approach!
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store