File: lib/stream.ts:47-66 (getStreamAddress)
export async function getStreamAddress(source, streamId, options?) {
if (isMock()) return MOCK_ADDRESSES[streamId.toString()] ?? null;
try {
const result = await simulateReadOnly(source, FACTORY()!, 'stream_address', [...]);
if (result.switch().name === 'scvVoid') return null;
return Address.fromScVal(result).toString();
} catch {
return null; // <-- every failure becomes "not found"
}
}
The bare catch { return null } collapses three very different outcomes to one:
- the factory returned
Void → stream genuinely doesn't exist
- the RPC call failed / timed out / rate-limited
FACTORY()! was undefined (unset NEXT_PUBLIC_FACTORY_CONTRACT_ID in
non-mock mode) → new Contract(undefined) threw deep in stellar-sdk
Callers (/stream/[id], fetchStreamsFromIndexer, dashboard) all treat null
as "Stream not found", so an outage or a misconfigured env shows the user
"Stream not found" for a stream that exists.
Suggested fix
Only return null for the scvVoid case; let real errors propagate (or wrap
them in a typed StreamLookupError) so the UI can show "couldn't reach the
network" vs "no such stream".
File:
lib/stream.ts:47-66(getStreamAddress)The bare
catch { return null }collapses three very different outcomes to one:Void→ stream genuinely doesn't existFACTORY()!wasundefined(unsetNEXT_PUBLIC_FACTORY_CONTRACT_IDinnon-mock mode) →
new Contract(undefined)threw deep in stellar-sdkCallers (
/stream/[id],fetchStreamsFromIndexer, dashboard) all treatnullas "Stream not found", so an outage or a misconfigured env shows the user
"Stream not found" for a stream that exists.
Suggested fix
Only return
nullfor thescvVoidcase; let real errors propagate (or wrapthem in a typed
StreamLookupError) so the UI can show "couldn't reach thenetwork" vs "no such stream".