xpipe-io/xpipe · error · IllegalArgumentException
Principals must not be empty
Error message
Principals must not be empty
What it means
DataStoreAccessScope is an immutable scope of encryption principals; its private constructor requires at least one principal because an access scope with no principals is meaningless — nothing could decrypt data in it. It throws IllegalArgumentException immediately when handed an empty set.
Source
Thrown at app/src/main/java/io/xpipe/app/storage/DataStoreAccessScope.java:101
public static DataStoreAccessScope vault() {
return new DataStoreAccessScope(
Set.of(DataStorageAccessHandler.getInstance().getFallbackPrincipal()));
}
public static DataStoreAccessScope encryption() {
return new DataStoreAccessScope(
Set.of(DataStorageAccessHandler.getInstance().getEncryptAllPrincipal()));
}
public static DataStoreAccessScope of(Set<EncryptionPrincipal> encryptionPrincipals) {
return new DataStoreAccessScope(encryptionPrincipals);
}
private final Set<EncryptionPrincipal> principals;
private DataStoreAccessScope(Set<EncryptionPrincipal> principals) {
if (principals.isEmpty()) {
throw new IllegalArgumentException("Principals must not be empty");
}
var vault = DataStorageAccessHandler.getInstance().getFallbackPrincipal();
var encrypt = DataStorageAccessHandler.getInstance().getEncryptAllPrincipal();
if (principals.contains(vault)) {
this.principals = treeSet(Set.of(vault));
} else if (principals.contains(encrypt)) {
this.principals = treeSet(Set.of(encrypt));
} else {
this.principals = treeSet(principals);
}
}
public boolean isAccessSubRestricted() {
var all = this.equals(encryption()) || this.equals(vault());
return !all;
}
View on GitHub (pinned to d85ca821ba)
Solutions
- Ensure the principal set has at least one entry before constructing the scope; bail out earlier with a clear message if the list is empty.
- Fall back to the vault principal (DataStorageAccessHandler.getInstance().getFallbackPrincipal()) when no user principals are available.
- Fix the upstream filtering logic so allowed principals are actually collected.
Example fix
// before
var scope = DataStoreAccessScope.of(collectedPrincipals); // throws when empty
// after
if (collectedPrincipals.isEmpty()) {
collectedPrincipals = Set.of(DataStorageAccessHandler.getInstance().getFallbackPrincipal());
}
var scope = DataStoreAccessScope.of(collectedPrincipals); Defensive patterns
Strategy: validation
Validate before calling
if (principals == null || principals.isEmpty()) {
throw new IllegalArgumentException("At least one encryption principal is required");
} Try / catch
try {
var scope = DataStoreAccessScope.of(principals);
} catch (IllegalArgumentException e) {
// fall back to the vault principal
} Prevention
- Never construct scopes from unfiltered, possibly empty principal sets.
- Fall back to the fallback principal when user filtering yields nothing.
- Log which filtering step removed all principals.
When it happens
Trigger: Calling DataStoreAccessScope.of()/factory or the private constructor path with an empty Set<EncryptionPrincipal>, e.g. after filtering principals and getting an empty result, or building a scope from a collection that was never populated.
Common situations: Computing the intersection of allowed principals across users and getting an empty set; loading principal lists from config/vault where none were found; filtering out principals the current user cannot access.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Secret is not accessible
- Unable to change scope from raw value with null value
- Name is empty
- Encrypted value is null
- Principal ${name} is not accessible
AI-assisted analysis of xpipe-io/xpipe@d85ca821ba (2026-09-06).
Data as JSON: /api/errors/62ee2d9a0ff84c0d.
Report an issue: GitHub.