List User cannot get all users
Checklist
- [x] I have looked into the README and have not found a suitable solution or answer.
- [x] I have looked into the documentation and have not found a suitable solution or answer.
- [x] I have searched the issues and have not found a suitable solution or answer.
- [x] I have upgraded to the latest version of OpenFGA and the issue still persists.
- [x] I have searched the Slack community and have not found a suitable solution or answer.
- [x] I agree to the terms within the OpenFGA Code of Conduct.
Description
Description
When using the listUsers API to list all users who have the viewer relation on a folder, the response does not include all users that should be inferred through indirect or inherited relationships.
However, using the check API for the same users and relation returns true, which indicates that the relationship is correctly modeled in the store.
var request = new ClientListUsersRequest()
._object(new FgaObject().type("folder").id(id))
.relation("viewer")
.userFilters(List.of(
new UserTypeFilter().type("user")
));
var response = fgaClient.listUsers(request);
Authorization Model
type user
type group
relations
define child: [group]
define member: [user] or member from child
define owner: [user, group#owner] or owner from parent
define parent: [group]
type folder
relations
define can_share: editor
define viewer: [user, group#member] or owner or editor or viewer from parent
define editor: [user, group#member] or owner or editor from parent
define owner: [user, group#owner] or owner from parent
define parent: [folder]
Tutples
user:user1 owner group:1
user:user2 member group:1
group:1#owner owner folder:1
group:1#member editor folder:1
folder:1 parent folder:3
From the model and tuples:
user1 → owner of group:1 → owner of folder:1 → viewer of folder:1 → viewer of folder:3
user2 → member of group:1 → editor of folder:1 → editor of folder:3 → viewer of folder:3
Using check(user2, viewer, folder:3) returns true
But listUsers(folder:3, viewer) does not return user2 (but do have user1)
Reproduction
Expectation
listUsers should return both user1 and user2 since both effectively have the viewer relation on folder:3 via inheritance and group membership.
Reproduction
-
Create the model above.
-
Insert the tuples as shown.
-
Run check for user2 viewer folder:3 → returns true.
-
Run listUsers(folder:3, viewer) → user2 (and possibly user1) missing.
OpenFGA SDK version
0.2.0
OpenFGA version
SDK Configuration
normal setting
Logs
No response
References
No response
Hi @Lin064 - before migrating this issue over to the server - can you clarify:
- What version of OpenFGA are you using?
- How many results are you expecting?
- How many total results are you getting?
- How long is the request taking?
- What are the values (if any) that you have set for the following configuration options:
OPENFGA_MAX_CONCURRENT_READS_FOR_LIST_USERSOPENFGA_LIST_USERS_MAX_RESULTS(note that by default it is 1000)OPENFGA_LIST_USERS_DEADLINE(note that by default it is 3s)
And any other List Users config overrides, see: https://openfga.dev/docs/getting-started/setup-openfga/configuration
Finally whether you are getting the same result when not using the Java SDK (try calling directly through the FGA CLI, curl or postman)
Please note that the endpoint does not throw an error if you hit those configured limits,and just returns what it found - if you are instrested in that, please thumbs up and subscribe to this issue on the server: https://github.com/openfga/openfga/issues/1961
I’m using the OpenFGA version from this Docker image: https://hub.docker.com/r/openfga/openfga/tags?name=1e84deddc7c84de8344f3eb0d443c5439666198b68ac37c24fd76fd2e8c1f629
In my test environment, I expect to get 2 results (user1 and user2), but I only receive 1 result (user1, who is the owner).
The request completes almost instantly.
All configuration values are set to their default settings
When I use the CLI directly (instead of the Java SDK), I get both user1 and user2 as expected.
The following images are provided as reference. (Sorry, I added two extra users while testing other functionality, but they should still clearly demonstrate the difference between the CLI and the Java SDK results.)
Hi @Lin064, thanks for providing detailed info!
I am unable to reproduce this with version 0.9.1 of the java SDK.
I have the following model:
model
schema 1.1
type user
type group
relations
define child: [group]
define member: [user] or member from child
define owner: [user, group#owner] or owner from parent
define parent: [group]
type folder
relations
define can_share: editor
define editor: [user, group#member] or owner or editor from parent
define owner: [user, group#owner] or owner from parent
define parent: [folder]
define viewer: [user, group#member] or owner or editor or viewer from parent
And these tuples:
{
"continuation_token":"",
"tuples": [
{
"key": {
"object":"group:1",
"relation":"member",
"user":"user:2"
},
"timestamp":"2025-10-21T20:31:07.957Z"
},
{
"key": {
"object":"folder:1",
"relation":"owner",
"user":"group:1#owner"
},
"timestamp":"2025-10-21T20:31:50.76Z"
},
{
"key": {
"object":"folder:3",
"relation":"parent",
"user":"folder:1"
},
"timestamp":"2025-10-21T20:32:40.7Z"
},
{
"key": {
"object":"group:1",
"relation":"owner",
"user":"user:1"
},
"timestamp":"2025-10-21T20:30:47.534Z"
},
{
"key": {
"object":"folder:1",
"relation":"editor",
"user":"group:1#member"
},
"timestamp":"2025-10-21T20:32:06.34Z"
}
]
}
Trying check:
$ fga query check user:2 viewer folder:3
{
"allowed":true,
"resolution":""
}
And list users:
$ fga query list-users --object folder:3 --relation viewer --user-filter user
{
"users": [
{
"object": {
"id":"1",
"type":"user"
}
},
{
"object": {
"id":"2",
"type":"user"
}
}
]
Running this test using version 0.9.1 of the Java SDK, with the same store shows list users working as expected:
OpenFGA Java SDK Test - Testing GitHub Issue #236
===================================================
Test 1: Check user:2 viewer folder:3
=====================================
Check result: true
Resolution:
Test 2: List users with viewer relation to folder:3
===================================================
List users result:
- User: user:1
- User: user:2
Test 3: Check user:2 member group:1
===================================
Check result: true
Resolution:
Test 4: List users with member relation to group:1
=================================================
List users result:
- User: user:2
Test completed!
Can you confirm what version of the Java SDK you are using and that you still observe the issue? If so, would you be able to share some more info or code so that we can reproduce the issue you are seeing? Thanks!
Hi, thanks for the reply! I think the issue might be related to the fact that the latest version available on Maven Central(openfga-spring-boot-starter) , which still use version 0.8.1 version commit
There are any plans to upload the latest version to Maven soon?
Hi @Lin064 I just ran this this test app with v0.8.1 of the Java SDK and get the same results (list users returning user:1 and user:2 for viewer of folder:3).
Would you be able to test with that example and verify behavior, and/or provide an example where I can reproduce the issue? I'm seeing the same list users behavior with the model and tuples I showed above, with the CLI and the Java SDK v0.8.1 and v0.9.1.
Oh and yes, we do plan on updating the java SDK dependency in spring-boot soon. Thanks!
Hi @jimmyjames , That’s a bit strange — I think our model and tuples are essentially the same. Here’s my current model: Model
model
schema 1.1
type user
type group
relations
define child: [group]
define member: [user] or member from child
define owner: [user, group#owner] or owner from parent
define parent: [group]
type folder
relations
define can_share: editor
define editor: [user, group#member] or owner or editor from parent
define owner: [user, group#owner] or owner from parent
define parent: [folder]
define viewer: [user, group#member] or owner or editor or viewer from parent or editor from parent
Tuples
I’m using the dependency:
<dependency>
<groupId>dev.openfga</groupId>
<artifactId>openfga-sdk</artifactId>
<version>0.9.1</version>
</dependency>
I copied your example code, but I’m using an apiToken for authentication (I assume that shouldn’t affect the behavior).
Here’s my test code:
package org.example;
import dev.openfga.sdk.api.client.OpenFgaClient;
import dev.openfga.sdk.api.client.model.ClientCheckRequest;
import dev.openfga.sdk.api.client.model.ClientListUsersRequest;
import dev.openfga.sdk.api.configuration.ApiToken;
import dev.openfga.sdk.api.configuration.ClientConfiguration;
import dev.openfga.sdk.api.configuration.Credentials;
import dev.openfga.sdk.api.model.CheckResponse;
import dev.openfga.sdk.api.model.FgaObject;
import dev.openfga.sdk.api.model.ListUsersResponse;
import dev.openfga.sdk.api.model.UserTypeFilter;
import dev.openfga.sdk.errors.FgaInvalidParameterException;
import java.util.concurrent.ExecutionException;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args ) throws FgaInvalidParameterException, ExecutionException, InterruptedException {
ClientConfiguration config = new ClientConfiguration()
.apiUrl("MYURL")
.storeId("MYSTOREID")
.authorizationModelId("MY MODELID")
.credentials(new Credentials(new ApiToken("MY TOKEN")))
;
OpenFgaClient client = new OpenFgaClient(config);
// Test 1: Test testUser2 viewer and editor assert
System.out.println("Test 1: Test testUser2 viewer and editor assert to folder:testFolder1");
try {
ClientCheckRequest checkRequest = new ClientCheckRequest()
.user("user:testUser2")
.relation("viewer")
._object("folder:testFolder1");
CheckResponse checkResponse = client.check(checkRequest).get();
System.out.println("Check viewer result: " + checkResponse.getAllowed());
System.out.println("Editor resolution: " + checkResponse.getResolution());
ClientCheckRequest checkEditorRequest = new ClientCheckRequest()
.user("user:testUser2")
.relation("editor")
._object("folder:testFolder1");
CheckResponse checkEditorResponse = client.check(checkEditorRequest).get();
System.out.println("Check editor result: " + checkEditorResponse.getAllowed());
System.out.println("Editor resolution: " + checkEditorResponse.getResolution());
} catch (Exception e) {
System.err.println("Check failed: " + e.getMessage());
e.printStackTrace();
}
// Test 2: List users who are viewers of folder:testFolder1
System.out.println("Test 2: List users with viewer relation to folder:testFolder1");
System.out.println("===================================================");
try {
ClientListUsersRequest listUsersRequest = new ClientListUsersRequest()
._object(new FgaObject().type("folder").id("testFolder1"))
.relation("viewer")
.userFilters(java.util.List.of(
new UserTypeFilter().type("user")
));
ListUsersResponse listUsersResponse = client.listUsers(listUsersRequest).get();
System.out.println("List users result:");
if (listUsersResponse.getUsers() != null && !listUsersResponse.getUsers().isEmpty()) {
for (dev.openfga.sdk.api.model.User user : listUsersResponse.getUsers()) {
System.out.println(" - User: " + user.getObject().getType() + ":" + user.getObject().getId());
}
} else {
System.out.println(" No users found");
}
} catch (Exception e) {
System.err.println("List users failed: " + e.getMessage());
e.printStackTrace();
}
// Test 3: Additional check - user:2 member group:1
System.out.println("Test 3: Check user:testUser2 member group:testGroup1");
System.out.println("===================================");
try {
ClientCheckRequest checkRequest = new ClientCheckRequest()
.user("user:testUser2")
.relation("member")
._object("group:testGroup1");
CheckResponse checkResponse = client.check(checkRequest).get();
System.out.println("Check result: " + checkResponse.getAllowed());
System.out.println("Resolution: " + checkResponse.getResolution());
} catch (Exception e) {
System.err.println("Check failed: " + e.getMessage());
e.printStackTrace();
}
System.out.println();
// Test 4: List users who are members of group:1
System.out.println("Test 4: List users with member relation to group:testGroup");
System.out.println("=================================================");
try {
ClientListUsersRequest listUsersRequest = new ClientListUsersRequest()
._object(new FgaObject().type("group").id("testGroup1"))
.relation("member")
.userFilters(java.util.List.of(
new UserTypeFilter().type("user")
));
ListUsersResponse listUsersResponse = client.listUsers(listUsersRequest).get();
System.out.println("List users result:");
if (listUsersResponse.getUsers() != null && !listUsersResponse.getUsers().isEmpty()) {
for (dev.openfga.sdk.api.model.User user : listUsersResponse.getUsers()) {
System.out.println(" - User: " + user.getObject().getType() + ":" + user.getObject().getId());
}
} else {
System.out.println(" No users found");
}
} catch (Exception e) {
System.err.println("List users failed: " + e.getMessage());
e.printStackTrace();
}
System.out.println("\nTest completed!");
}
}
And here’s the result I get:
Test 1: Test testUser2 viewer and editor assert to folder:testFolder1
Check viewer result: false
Editor resolution:
Check editor result: true
Editor resolution:
Test 2: List users with viewer relation to folder:testFolder1
===================================================
List users result:
- User: user:testUser1
Test 3: Check user:testUser2 member group:testGroup1
===================================
Check result: true
Resolution:
Test 4: List users with member relation to group:testGroup
=================================================
List users result:
- User: user:testUser2
Test completed!
So it seems that in my setup, user:testUser2 is an editor (and member of the group), but doesn’t appear in the list of viewers for the folder — while in your test, both users are returned.
I also noticed that check(user:testUser2, viewer, folder:testFolder1) returns false. However, in the Playground, the same check shows that the relationship is connected — so my model and tuples should be correct?
here is the evidence that i use playground
Hi @Lin064, I updated my store with your updated model and the tuples you recently shared. I see the same results as you, and to the point of this issue, I see the same results from the CLI.
Model:
model
schema 1.1
type user
type group
relations
define child: [group]
define member: [user] or member from child
define owner: [user, group#owner] or owner from parent
define parent: [group]
type folder
relations
define can_share: editor
define editor: [user, group#member] or owner or editor from parent
define owner: [user, group#owner] or owner from parent
define parent: [folder]
define viewer: [user, group#member] or owner or editor or viewer from parent or editor from parent
Tuples:
{
"continuation_token":"",
"tuples": [
{
"key": {
"object":"folder:testFolder1",
"relation":"editor",
"user":"group:testGroup1#member"
},
"timestamp":"2025-10-27T15:25:02.687Z"
},
{
"key": {
"object":"group:testGroup2",
"relation":"member",
"user":"user:testUser2"
},
"timestamp":"2025-10-27T15:23:49.221Z"
},
{
"key": {
"object":"group:testGroup1",
"relation":"owner",
"user":"user:testUser1"
},
"timestamp":"2025-10-27T15:23:28.171Z"
},
{
"key": {
"object":"folder:testFolder1",
"relation":"owner",
"user":"group:testGroup1#owner"
},
"timestamp":"2025-10-27T15:24:32.976Z"
}
]
}
Java ouptput:
OpenFGA Java SDK Test - Testing GitHub Issue #236
===================================================
Test 1: Test testUser2 viewer and editor assert to folder:testFolder1
Check viewer result: true
Editor resolution:
Check editor result: true
Editor resolution:
Test 2: List users with viewer relation to folder:testFolder1
===================================================
List users result:
- User: user:testUser1
- User: user:testUser2
Test 3: Check user:testUser2 member group:testGroup1
===================================
Check result: true
Resolution:
Test 4: List users with member relation to group:testGroup
=================================================
List users result:
- User: user:testUser2
Test completed!
Executing the same calls with the CLI returned the same results.
CLI - testUser2 is viewer of folder:testFolder1:
$ fga query check user:testUser2 viewer folder:testFolder1
Using config file: /Users/jim.anderson/code/list-users-test/.fga.yaml
{
"allowed":true,
"resolution":""
}
CLI - testUser2 is editor of folder:testFolder1:
$ fga query check user:testUser2 editor folder:testFolder1
Using config file: /Users/jim.anderson/code/list-users-test/.fga.yaml
{
"allowed":true,
"resolution":""
}
CLI - listUsers for viewer of testFolder1:
$ fga query list-users --object folder:testFolder1 --relation viewer --user-filter user
Using config file: /Users/jim.anderson/code/list-users-test/.fga.yaml
{
"users": [
{
"object": {
"id":"testUser1",
"type":"user"
}
},
{
"object": {
"id":"testUser2",
"type":"user"
}
}
]
}
CLI - is testUser2 member of testGroup1:
$ fga query check user:testUser2 member group:testGroup1
Using config file: /Users/jim.anderson/code/list-users-test/.fga.yaml
{
"allowed":true,
"resolution":""
}
CLI - listUsers for member of testGroup1:
$ fga query list-users --object group:testGroup1 --relation member --user-filter user
Using config file: /Users/jim.anderson/code/list-users-test/.fga.yaml
{
"users": [
{
"object": {
"id":"testUser2",
"type":"user"
}
}
]
}
Are you still seeing results from the CLI or API behaving differently? The Java SDK (and CLI for that matter) are pretty thin wrappers of the HTTP API, so I don't think we'd see different results between the SDK and the API (and I don't see any obvious issues in the SDK code to that effect).
If you are still observing that the Java SDK is returning results that are different from the API, please update with reproduction steps as well as the exact model and tuples. Otherwise, I think we can close this issue as I'm not able to demonstrate the Java SDK returning different results than the API/CLI. Thanks!
Yes, I’m quite certain that the results I get from the FGA CLI are different from what I get when running through the JDK. I’m not sure about the exact reason, but I believe the model and tuple I mentioned above are the correct versions for my current environment.
Below are the results I got using the FGA CLI.
And this is my result from result from java project
Test 1: Test testUser2 viewer and editor assert to folder:testFolder1
===================================================
Check viewer result: false
Check editor result: true
===================================================
Test 2: List users with viewer relation to folder:testFolder1
===================================================
List users result:
- User: user:testUser1
As you mentioned, the Java SDK (as well as the CLI) is just a lightweight wrapper around the HTTP API, which is also why I find this behavior a bit confusing. If we’re unable to reproduce this issue, I think it’s fine to close it for now. If I later find the cause or a reliable way to reproduce it, I’ll follow up with you.
@jimmyjames I think we can close this issue. After upgrading old OpenFGA(v1.8.16) to the latest version, the Java SDK is returning the correct results on my side. (I’m still a bit puzzled about why the CLI returned the correct results while the JDK did not).
Anyway, upgrading to the latest release definitely resolved the problem. Thanks!