XRPC procedures with no output throw JsonException on every call #69
Labels
No labels
breaking-change
bug
documentation
duplicate
enhancement
good first issue
help wanted
performance
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Grandiras/ATProto.NET#69
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Every XRPC procedure whose Lexicon declares no output currently asks for a deserialized response, so it throws on the empty body a real server returns:
These methods fail on every call against a real PDS or appview, regardless of what the server does. It is not a corner of the API —
PutPreferencesAsync, the six mute/unmute methods,UpdateSeenAsync,RegisterPushAsyncandUpdateHandleAsyncare ordinary client calls.Cause
XrpcClient.ProcedureAsync<TRequest, TResponse>ends inReadFromJsonAsync, which throws on an empty payload. The affected methods passobjectasTResponseand discard the result:A body-only overload,
ProcedureAsync<TRequest>, already exists and is the correct call.Affected call sites (19)
IdentityClientupdateHandle,submitPlcOperation,requestPlcOperationSignatureSyncClientnotifyOfUpdate,requestCrawlActorClientputPreferencesGraphClientmuteActor,unmuteActor,muteActorList,unmuteActorList,muteThread,unmuteThreadNotificationClientupdateSeen,registerPushcommunication.deleteTemplate,team.deleteMember,set.addValues,set.deleteValues,set.deleteSet18 of the 19 declare no
outputupstream.tools.ozone.set.deleteSetdoes declare one, but the method discards it, so deserializing only creates a way to fail.The seven equivalents in
AdminClientwere fixed in #68, where the managed-PDS work depends on them and integration tests against a live PDS cover them.Why the tests didn't catch it
The existing test doubles return
{}, which deserializes perfectly well. The defect only appears against a server that returns nothing — which is what these endpoints do. It was found by runningPdsAdminClientagainst a realghcr.io/bluesky-social/pdscontainer for the first time.Fix
Switch the 19 call sites to
ProcedureAsync<TRequest>. No public signatures change: every one of these methods already returnsTaskand discards the value.Add a regression test that answers 200 with an empty body, the way a real server does, and drives all 19 NSIDs through the public client API.
Impact
Affects released versions. Any consumer calling mute/unmute,
PutPreferencesAsync,UpdateSeenAsync,RegisterPushAsync,UpdateHandleAsync,RequestCrawlAsync, or the Ozone set/team/communication mutators gets an exception instead of a completed call.