Repository navigation
Graph API driveItem invite fails with CODE_INTERNAL when sharing with an accepted OCM/federated user #3262
Description
Summary
Creating a federated share via the Graph API driveItem/invite endpoint fails with a generic internal error, even though the OCM invitation handshake (generate-invite / accept-invite) between the two instances completed successfully and is verifiable via the sciencemesh API.
Environment
OpenCloud 7.4.0 (rolling). Two independent self-hosted instances, embedded IDM (no external LDAP) on either side. OC_ENABLE_OCM=true on both instances. Matching ocmproviders.json declaring mutual trust between both domains.
Steps to reproduce
Step 1: On instance A (a.example.com), authenticate as user A and call POST /sciencemesh/generate-invite. Returns a token and expiration.
Step 2: On instance B (b.example.com), authenticate as user B and call POST /sciencemesh/accept-invite with the token and providerDomain=a.example.com. Returns HTTP 200.
Step 3: Confirm the handshake on both instances via GET /sciencemesh/find-accepted-users. Both sides correctly list each other as an accepted federated user. This part works as documented.
Step 4: On instance A, attempt to share an existing personal folder with user B via the Graph API:
POST /graph/v1beta1/drives/{driveId}/items/{itemId}/invite
Content-Type: application/json
{
"recipients": [
{
"objectId": "@https://b.example.com",
"@libre.graph.recipient.type": "user"
}
],
"roles": ["b1e2218d-eef8-4d4c-b82d-0f1a1b48f3b5"]
}
Expected result
Per services/ocm/README.md: "we allow creating federated shares using the graph API. Clients can now discover the available sharing roles and invite federated users using the graph API." The share should be created as an OCM share.
Actual result
HTTP 400 with body:
error.code = invalidRequest
error.message = generalException: unexpected status code while getting accepted user: CODE_INTERNAL
Investigation
Traced through the source (main branch, commit-pinned dependency github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260310090739-853d972b282d).
DriveItemPermissionsService.Invite() in services/graph/pkg/service/v0/api_driveitem_permissions.go correctly detects that objectID is not a local user (identityCache.GetCS3User returns ErrNotFound), and since IncludeOCMSharees is enabled, falls back to identityCache.GetAcceptedCS3User(ctx, objectID) in services/graph/pkg/identity/cache/cache.go.
GetAcceptedCS3User parses the composite id via getIDAndMeshProvider, builds a cs3User.UserId{Idp, OpaqueId, Type: USER_TYPE_FEDERATED}, and calls revautils.GetAcceptedUserWithContext() (github.com/opencloud-eu/reva/v2/pkg/utils), which calls gwc.GetAcceptedUser(ctx, invitev1beta1.GetAcceptedUserRequest{RemoteUserId: userID}).
This gRPC call returns status CODE_INTERNAL, which checkStatusCode("getting accepted user", ...) turns into the generic error surfaced above.
So the failure is inside the gateway's GetAcceptedUser RPC handler, not in the Graph API request itself. The same federated user is correctly resolved by the sciencemesh HTTP API (find-accepted-users) moments earlier, so the underlying invitation data is intact; something in the gRPC path specifically breaks.
This appears to block the entire create-a-federated-share-via-the-Graph-API flow documented in services/ocm/README.md, since every code path for a federated recipient depends on this lookup succeeding.
Possibly related to the ongoing OCM compliance work in opencloud-eu/reva#383.
Additional context
objectId format tried: opaque-id@https://domain (as returned by /sciencemesh/find-accepted-users), also tried without the https:// prefix and with just the opaque id, same error in all variants.
Role ID used (b1e2218d-eef8-4d4c-b82d-0f1a1b48f3b5, Can view) is valid and works correctly for local-user invites on the same folder.
IncludeOCMSharees must be enabled on this deployment, since the code path reaches the OCM-specific lookup at all (with it disabled, the error would instead be the earlier generic failed-user-lookup error for a plain not-found user).
Activity
micbar commentedon Aug 14, 2026
@butonic @dragotin FYI
patxixi commentedon Aug 14, 2026
Please also refer to link issue opencloud-eu/web#4039. Thanks !
VicDeo commentedon Aug 18, 2026
@patxixi
Expected
objectIdformatThe recipient must match how accepted users are stored after the invitation exchange. In practice, clients must build it from GET /sciencemesh/find-accepted-users:
objectId = user_id + "@" + idp
E.g.
in this case the expected recipient is exactly
It looks ugly and the most likely the invitation exchange process lacks proper remote user id normalization.
So it doesn't work this way (
056fc874-dd7f-11ef-ba84-af6fca4b7289@https://cloud2.opencloud.test:10200):neither this way (
056fc874-dd7f-11ef-ba84-af6fca4b7289@cloud2.opencloud.test:10200):But this way it works (
056fc874-dd7f-11ef-ba84-af6fca4b7289@https://cloud2.opencloud.test:10200@cloud2.opencloud.test:10200):VicDeo commentedon Aug 18, 2026
According to OCM spec OCM address is
identifier@host[:port]with no scheme.The invite-accepted userID should be the bare identifier; the provider host travels separately in recipientProvider.
So the solution would be store the
opaque_idcorrectly(and probably fallback to the old format for the backward compatibility)
should be stored as
"opaque_id": "b1f74ec4-dd7e-11ef-a543-03775734d0f7",The same applies to the user-id sent on the invite accept.
patxixi commentedon Aug 18, 2026
Thanks @VicDeo, this workaround unblocked me completely.
For context: I'm running 3 separate OpenCloud instances (personal family setup, one primary user per instance plus a couple of secondary accounts) and hit the exact same
CODE_INTERNALerror onPOST /graph/v1beta1/drives/{driveid}/items/{itemid}/invitewhen trying to share a folder with an already-accepted OCM/federated user.Confirmed your finding and workaround work in my real-world setup, not just the reproduction case:
objectId(user_id@idp@idpinstead of theuser_id@idpreturned by/sciencemesh/find-accepted-users) makes the invite succeed every time.items/{itemId}segment in the invite URL needs to be the fulldriveId!itemIdform, not just the bare item id — using just the item id returnsinvalid driveID or itemID(422).After applying both, I built out a real bidirectional test: a shared folder on one instance, invited out to accepted federated users on the other two, each side uploading a file and confirming it shows up for everyone else. Full sync worked correctly in both directions once the shares were created this way.
Separate observation while testing, possibly worth its own issue: I got a share notification for a local share (same instance, two accounts on the same host) as expected, but got no notification at all for the OCM/federated shares. Haven't dug further into whether that's specific to my setup or a general gap in the federated-share notification path.
Would be great to see the remote-user-id normalization fixed upstream so this doesn't need a workaround — happy to help verify a patch against my setup if useful.