grpc/grpc-java · error · GeneralSecurityException
Files were unmodified before their initial update. Probably…
Error message
Files were unmodified before their initial update. Probably a bug.
What it means
This one-shot updateTrustCredentials(File) call returns the file's new modification time from readAndUpdate; a return value of 0 means the file's lastModified() did not change from the initial value (0), so no credentials were read. The library treats this as an internal invariant violation — the very first read should always register a modification time.
Solutions
- Verify the trust certificate file exists and is readable, and that its filesystem reports a valid modification time (File.lastModified() > 0) before calling
- Re-read the file / retry the update call once the file is stable on disk
- If the file is actively rotated, ensure the rotation is atomic (write temp file + rename) so lastModified() and the read are consistent
- Report as a bug if the file is a regular local file with a valid mtime — the library comment says 'Probably a bug'
Example fix
// before
manager.updateTrustCredentials(trustCertFile); // throws if mtime is 0
// after
if (trustCertFile.exists() && trustCertFile.lastModified() > 0) {
manager.updateTrustCredentials(trustCertFile);
} else {
throw new IOException("Trust cert file missing or has invalid mtime: " + trustCertFile);
} Defensive patterns
Strategy: validation
Validate before calling
if (trustCertFile == null || !trustCertFile.exists() || trustCertFile.lastModified() == 0) {
throw new IOException("Trust cert file missing or unreportable mtime: " + trustCertFile);
}
trustManager.updateTrustCredentials(trustCertFile); Try / catch
try {
manager.updateTrustCredentials(trustCertFile);
} catch (GeneralSecurityException e) {
if (e.getMessage().contains("Files were unmodified before their initial update")) {
log.warning("Initial trust update failed; verify file mtime/filesystem: " + trustCertFile);
}
throw e;
} Prevention
- Check File.lastModified() > 0 before calling updateTrustCredentials
- Keep trust files on local filesystems that report modification times
- Rotate certificate files atomically via rename
- Treat persistent occurrences on ordinary files as a library bug and report it
When it happens
Trigger: Calling public void updateTrustCredentials(File trustCertFile) when readAndUpdate(trustCertFile, 0) returns 0. Since oldTime is 0, this only happens when File.lastModified() returns 0, i.e. the file does not exist or is not readable — normally that path throws the IOException from readAndUpdate first, so reaching 0 here indicates a race or filesystem anomaly (lastModified()==0 but FileInputStream succeeded, e.g. on odd filesystems).
Common situations: Files on exotic/network filesystems where lastModified() returns 0; a file deleted or replaced between the lastModified() check and the read; TOCTOU races in rapidly rotating certificate files.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Certificate file not found or not readable
- A key manager is required
- ca_certificate_provider_instance name
- ca_certificate_provider_instance or system_root_certs is…
- Can't set TLS settings for ALTS
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/71b8e113ff54cc71.
Report an issue: GitHub.
Appendix: source
Thrown at util/src/main/java/io/grpc/util/AdvancedTlsX509TrustManager.java:231
int i = 1;
for (X509Certificate cert: trustCerts) {
String alias = Integer.toString(i);
keyStore.setCertificateEntry(alias, cert);
i++;
}
this.delegateManager = createDelegateTrustManager(keyStore);
}
/**
* Updates the trust certificates from a local file path.
*
* @param trustCertFile the file on disk holding the trust certificates
*/
public void updateTrustCredentials(File trustCertFile) throws IOException,
GeneralSecurityException {
long updatedTime = readAndUpdate(trustCertFile, 0);
if (updatedTime == 0) {
throw new GeneralSecurityException(
"Files were unmodified before their initial update. Probably a bug.");
}
}
/**
* Schedules a {@code ScheduledExecutorService} to read trust certificates from a local file path
* periodically, and updates the cached trust certs if there is an update. You must close the
* returned Closeable before calling this method again or other update methods
* ({@link AdvancedTlsX509TrustManager#useSystemDefaultTrustCerts()},
* {@link AdvancedTlsX509TrustManager#updateTrustCredentials(X509Certificate[])},
* {@link AdvancedTlsX509TrustManager#updateTrustCredentialsFromFile(File)}).
* Before scheduling the task, the method synchronously reads and updates trust certificates once.
* If the provided period is less than 1 minute, it is automatically adjusted to 1 minute.
*
* @param trustCertFile the file on disk holding the trust certificates
* @param period the period between successive read-and-update executions
* @param unit the time unit of the initialDelay and period parameters
* @param executor the executor service we use to read and update the credentialsView on GitHub (pinned to 64daddc1f3)