microg/GmsCore · error · IllegalArgumentException
rolling period missing
Error message
rolling period missing
What it means
TemporaryExposureKeyProto.toKey() requires rolling_period (key validity length in 10-minute intervals). If the received proto omits it, IllegalArgumentException 'rolling period missing' is thrown, since risk calculation and key matching depend on this field.
Source
Thrown at play-services-nearby/core/src/main/kotlin/org/microg/gms/nearby/exposurenotification/ExposureNotificationServiceImpl.kt:250
ExposureDatabase.with(context) { database ->
database.noteAppAction(packageName, "getTemporaryExposureKeyHistory", JSONObject().apply {
put("result", status.statusCode)
put("response_keys_size", response.size)
}.toString())
}
try {
params.callback.onResult(status, response)
} catch (e: Exception) {
Log.w(TAG, "Callback failed", e)
}
}
}
private fun TemporaryExposureKeyProto.toKey(): TemporaryExposureKey = TemporaryExposureKey.TemporaryExposureKeyBuilder()
.setKeyData(key_data?.toByteArray() ?: throw IllegalArgumentException("key data missing"))
.setRollingStartIntervalNumber(rolling_start_interval_number
?: throw IllegalArgumentException("rolling start interval number missing"))
.setRollingPeriod(rolling_period ?: throw IllegalArgumentException("rolling period missing"))
.setTransmissionRiskLevel(transmission_risk_level ?: 0)
.build()
private fun InputStream.copyToFile(outputFile: File) {
outputFile.outputStream().use { output ->
copyTo(output)
output.flush()
}
}
private fun MessageDigest.digest(file: File): ByteArray = file.inputStream().use { input ->
val buf = ByteArray(4096)
var bytes = input.read(buf)
while (bytes != -1) {
update(buf, 0, bytes)
bytes = input.read(buf)
}
digest()View on GitHub (pinned to 157c9d86ac)
Solutions
- Validate rolling_period is present and within the expected range (e.g. 1-144) before conversion
- Re-fetch the export file and verify integrity (signature/checksum)
- Skip entries with missing rolling_period and log a warning
- Fix the upstream diagnosis key server to emit complete TEK protos
Example fix
// before
.setRollingPeriod(rolling_period ?: throw IllegalArgumentException("rolling period missing"))
// after
val period = rolling_period?.takeIf { it in 1..144 } ?: run { Log.w(TAG, "invalid rolling period"); return null }
.setRollingPeriod(period) Defensive patterns
Strategy: validation
Validate before calling
fun TemporaryExposureKeyProto.hasValidRollingPeriod(): Boolean =
rolling_period != null && rolling_period in 1..144 Type guard
fun TemporaryExposureKeyProto?.isConvertibleToKey(): Boolean =
this != null && key_data?.size() ?: 0 > 0 && rolling_start_interval_number != null && rolling_period != null Try / catch
try {
val key = proto.toKey()
} catch (e: IllegalArgumentException) {
if (e.message?.contains("rolling period") == true) skipEntry(proto)
else throw e
} Prevention
- Check rolling_period presence and range before conversion
- Verify export file integrity before parsing
- Skip and log entries with invalid rolling periods
- Fix upstream key servers to always emit rolling_period
When it happens
Trigger: Converting a TemporaryExposureKeyProto from an export file or server response where rolling_period is unset; malformed diagnosis keys fetched by provideDiagnosisKeys.
Common situations: Noncompliant diagnosis servers omitting rolling_period; truncated/corrupt key archives; older export formats or hand-built test protos missing the field.
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
- key data missing
- rolling start interval number missing
- deleteAll was set to true but keys were also provided
- Element in keys cannot be null or empty
- deleteAll=true but keys are provided
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/f60dce04f4d11713.
Report an issue: GitHub.