xpipe-io/xpipe · error · IllegalStateException
Secret is not accessible
Error message
Secret is not accessible
What it means
MultiPrincipalSecret.withUpdatedPrincipals() re-encrypts the secret for the target access scope. It refuses to run when no principal's copy of the secret is currently accessible (isAnyAccessible() is false), because there would be no readable secret material to carry into the new scope. The library throws IllegalStateException since the caller has asked for an operation that is impossible in the current state.
Source
Thrown at app/src/main/java/io/xpipe/app/secret/MultiPrincipalSecret.java:253
var ar = JsonNodeFactory.instance.arrayNode();
for (var e : entries) {
var node = JsonNodeFactory.instance.objectNode();
node.put("name", e.getPrincipal().getName());
node.put("principal", e.getPrincipal().getUuid().toString());
node.put("iteration", e.getIteration());
node.put("secret", e.getEncrypted());
node.set("token", JacksonMapper.getDefault().valueToTree(e.getToken()));
ar.add(node);
}
var secretsNode = JsonNodeFactory.instance.objectNode();
secretsNode.set("secrets", ar);
return secretsNode;
}
public MultiPrincipalSecret withUpdatedPrincipals() {
if (!isAnyAccessible()) {
throw new IllegalStateException("Secret is not accessible");
}
var scope = getScope();
var targetScope = DataStoreAccessScope.getTargetScope(scope);
return with(secret, targetScope);
}
public InPlaceSecretValue getInternalSecret() {
return secret;
}
}
View on GitHub (pinned to d85ca821ba)
Solutions
- Ensure the secret is readable first: check isAnyAccessible() and unlock the vault / supply the correct storage passphrase before calling withUpdatedPrincipals().
- Re-enter or reset the vault credentials so at least one principal can decrypt the secret, then retry.
- If the secret can never be decrypted, re-create it with fresh values instead of migrating it.
Example fix
// before
secret.withUpdatedPrincipals(); // throws if nothing is accessible
// after
if (secret.isAnyAccessible()) {
secret.withUpdatedPrincipals();
} else {
throw new UserException("Secret is locked; unlock the vault first");
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!secret.isAnyAccessible()) {
throw new IllegalStateException("Unlock the vault before re-encrypting this secret");
} Type guard
boolean canRescope(MultiPrincipalSecret s) { return s.isAnyAccessible(); } Try / catch
try {
secret.withUpdatedPrincipals();
} catch (IllegalStateException e) {
// prompt user to unlock the vault / fix encryption principal
} Prevention
- Check isAnyAccessible() before any scope-migration call.
- Keep vault credentials consistent across machines.
- Handle Encrypt All mode changes by re-validating secrets afterwards.
When it happens
Trigger: Calling withUpdatedPrincipals() when every underlying encrypted value fails to decrypt — e.g. the vault key/principal that stored the secret is unavailable, the secret was stored by another user, or encryption state was invalidated (Encrypt All mode changes).
Common situations: Opening a vault on a machine where the storage passphrase/principal differs from the one that encrypted the secrets; after enabling 'encrypt all' or changing encryption settings so old secrets are no longer readable; programmatically migrating secrets with a partially-loaded vault.
Understand the failure class
Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.
Related errors
- Principal ${name} is not accessible
- Scope ${scope} is not supported
- No secret available to encrypt
- Unable to change scope from raw value with null value
- Principals must not be empty
AI-assisted analysis of xpipe-io/xpipe@d85ca821ba (2026-09-06).
Data as JSON: /api/errors/6f7845101823c25e.
Report an issue: GitHub.