beemdevelopment/Aegis · error · CertificateException
signatures cannot be null or empty!
Error message
signatures cannot be null or empty!
What it means
TrustedIntents.checkTrustedSigner validates that an APK's signature array is usable before comparing it against the pinned signer list. If the Signature[] is null or zero-length it throws CertificateException('signatures cannot be null or empty!') — there is nothing to compare, and treating that as 'untrusted' would hide the real cause.
Solutions
- Request signatures properly: getPackageInfo(pkg, PackageManager.GET_SIGNATURES) (or GET_SIGNING_CERTIFICATES + signingInfo on API 28+) and check the result before calling
- Verify the target package is actually installed and visible (manifest queries/package-visibility on Android 11+)
- Guard the call: if signatures == null || signatures.length == 0, fail with a clear message or re-fetch signatures rather than passing them through
- Use the newer checkTrustedSigner(SigningInfo) path on API 28+ where GET_SIGNATURES is unreliable
Example fix
// before
PackageInfo info = pm.getPackageInfo(pkg, 0);
trustedIntents.checkTrustedSigner(info); // CertificateException: signatures cannot be null or empty!
// after
PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
if (info == null || info.signatures == null || info.signatures.length == 0) {
Log.w(TAG, "No signatures for " + pkg + "; treating as untrusted");
return false;
}
trustedIntents.checkTrustedSigner(info); Defensive patterns
Strategy: type-guard
Validate before calling
PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
if (info == null || info.signatures == null || info.signatures.length == 0) {
throw new IllegalStateException("no signatures for " + pkg);
} Type guard
boolean hasUsableSignatures(PackageInfo info) {
return info != null && info.signatures != null && info.signatures.length > 0;
} Try / catch
try {
trustedIntents.checkTrustedSigner(info);
} catch (CertificateException e) {
Log.w(TAG, "signature data unavailable for " + pkg, e);
} catch (NameNotFoundException e) {
Log.w(TAG, "package not installed: " + pkg, e);
} Prevention
- Always request GET_SIGNATURES (or SigningInfo on API 28+) when fetching PackageInfo
- Confirm the package is installed and visible (Android 11+ package visibility)
- Never pass through signature arrays without a null/empty check
When it happens
Trigger: Calling checkTrustedSigner with a null or empty Signature[]; commonly from checkTrustedSigner(PackageInfo) where packageInfo.signatures is null — e.g. PackageManager could not retrieve signatures (GET_SIGNATURES not requested, app not installed, or platform returned none).
Common situations: Querying a package that isn't installed; calling getPackageInfo without GET_SIGNATURES on some Android versions; signature info stripped by app-bundle/installer tooling; work-profile/instant-app quirks returning null signatures.
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
- APK signatures did not match!
- Certificates cannot be null or empty!
- Unable to decode stream to bitmap
- Unable to find pack.json in the root of the ZIP file
- Attempted to write outside of the parent directory
AI-assisted analysis of beemdevelopment/Aegis@d6f4e5925a (2026-09-08).
Data as JSON: /api/errors/7938d15c05040ac1.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/main/java/info/guardianproject/trustedintents/TrustedIntents.java:228
}
return false;
}
public void checkTrustedSigner(String packageName)
throws NameNotFoundException, CertificateException {
PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
checkTrustedSigner(packageInfo.signatures);
}
public void checkTrustedSigner(PackageInfo packageInfo)
throws NameNotFoundException, CertificateException {
checkTrustedSigner(packageInfo.signatures);
}
public void checkTrustedSigner(Signature[] signatures)
throws NameNotFoundException, CertificateException {
if (signatures == null || signatures.length == 0)
throw new CertificateException("signatures cannot be null or empty!");
for (int i = 0; i < signatures.length; i++)
if (signatures[i] == null || signatures[i].toByteArray().length == 0)
throw new CertificateException("Certificates cannot be null or empty!");
// check whether the APK signer is trusted for all apps
for (ApkSignaturePin pin : pinList)
if (areSignaturesEqual(signatures, pin.getSignatures()))
return; // found a matching trusted APK signer
throw new CertificateException("APK signatures did not match!");
}
public boolean areSignaturesEqual(Signature[] sigs0, Signature[] sigs1) {
// TODO where is Android's implementation of this that I can just call?
if (sigs0 == null || sigs1 == null)
return false;
if (sigs0.length == 0 || sigs1.length == 0)
return false;View on GitHub (pinned to d6f4e5925a)