Summary
ATProtoKit.getBlob(from:cid:) -> Data (ComAtprotoSyncGetBlobMethod.swift) sends its request to a hardcoded https://bsky.network. Blobs are served by the PDS, not the relay — the bsky.network relay/firehose carries repo records but not blob binaries. So getBlob fails for any account whose PDS host is not literally bsky.network, which is effectively all real accounts — including mainstream Bluesky accounts on *.host.bsky.network and third-party PDSes. The sibling getRepository(by:sinceRevision:) carries the same bsky.network hardcode, but there the relay mirrors the repo, so it succeeds in practice; the defect is only user-visible for getBlob. (Other PDS-served com.atproto.sync.* wrappers — getBlocks, listBlobs, getLatestCommit, getRepoStatus, sync.getRecord — share the same hardcode.)
Reproduction Steps
- Authenticate with an account whose PDS host is not
bsky.network (e.g. a mainstream *.host.bsky.network account, or a third-party PDS such as eurosky.social).
- Call
getBlob(from: did, cid: someCID) for a blob that exists on that account's PDS (e.g. the avatar CID from getProfile).
- Observe the request goes to
https://bsky.network/xrpc/com.atproto.sync.getBlob, which does not serve the blob, and the call fails.
Expected Results
The request routes to the PDS that hosts the blob — the session's serviceEndpoint for the caller's own data, or the DID-resolved PDS for an arbitrary did — the same precedence #296 introduced for describeRepository / listRecords (explicit pdsURL → DID resolution → existing host).
Actual Results
The method hardcodes the host:
// ComAtprotoSyncGetBlobMethod.swift
guard let requestURL = URL(string: "https://bsky.network/xrpc/com.atproto.sync.getBlob") else { ... }
There is no pdsURL parameter and no PDS resolution. Verified on-device against 3 accounts (*.host.bsky.network ×2 and eurosky.social): getBlob failed on all three, while getRepository succeeded (the relay mirrors repos, but not blobs).
What operating systems did you experience this bug?
macOS
Operating System Version
- macOS Tahoe 26.5.2
- iOS 26.5.2
ATProtoKit Version
0.33.3
Additional Context
Suggested fix: add an optional pdsURL and route through the existing resolvePDSHost(for:), matching describeRepository / listRecords. Precedence: explicit pdsURL → resolvePDSHost(for: accountDID) → self.pdsURL. The bsky.network literal is intentionally dropped rather than kept as a fallback: the relay never serves blobs, so it is never a useful host for getBlob.
Summary
ATProtoKit.getBlob(from:cid:) -> Data(ComAtprotoSyncGetBlobMethod.swift) sends its request to a hardcodedhttps://bsky.network. Blobs are served by the PDS, not the relay — thebsky.networkrelay/firehose carries repo records but not blob binaries. SogetBlobfails for any account whose PDS host is not literallybsky.network, which is effectively all real accounts — including mainstream Bluesky accounts on*.host.bsky.networkand third-party PDSes. The siblinggetRepository(by:sinceRevision:)carries the samebsky.networkhardcode, but there the relay mirrors the repo, so it succeeds in practice; the defect is only user-visible forgetBlob. (Other PDS-servedcom.atproto.sync.*wrappers —getBlocks,listBlobs,getLatestCommit,getRepoStatus,sync.getRecord— share the same hardcode.)Reproduction Steps
bsky.network(e.g. a mainstream*.host.bsky.networkaccount, or a third-party PDS such aseurosky.social).getBlob(from: did, cid: someCID)for a blob that exists on that account's PDS (e.g. the avatar CID fromgetProfile).https://bsky.network/xrpc/com.atproto.sync.getBlob, which does not serve the blob, and the call fails.Expected Results
The request routes to the PDS that hosts the blob — the session's
serviceEndpointfor the caller's own data, or the DID-resolved PDS for an arbitrarydid— the same precedence#296introduced fordescribeRepository/listRecords(explicitpdsURL→ DID resolution → existing host).Actual Results
The method hardcodes the host:
There is no
pdsURLparameter and no PDS resolution. Verified on-device against 3 accounts (*.host.bsky.network×2 andeurosky.social):getBlobfailed on all three, whilegetRepositorysucceeded (the relay mirrors repos, but not blobs).What operating systems did you experience this bug?
macOS
Operating System Version
ATProtoKit Version
0.33.3
Additional Context
Suggested fix: add an optional
pdsURLand route through the existingresolvePDSHost(for:), matchingdescribeRepository/listRecords. Precedence: explicitpdsURL→resolvePDSHost(for: accountDID)→self.pdsURL. Thebsky.networkliteral is intentionally dropped rather than kept as a fallback: the relay never serves blobs, so it is never a useful host forgetBlob.