microg/GmsCore · error · IllegalArgumentException
key data missing
Error message
key data missing
What it means
TemporaryExposureKeyProto.toKey() converts a protobuf-encoded exposure key into the API TemporaryExposureKey object. The key_data field is mandatory; when the proto was received without key data, the elvis operator throws IllegalArgumentException 'key data missing' instead of building a key with null/empty key material.
Source
Thrown at play-services-nearby/core/src/main/kotlin/org/microg/gms/nearby/exposurenotification/ExposureNotificationServiceImpl.kt:247
else -> emptyList()
}
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)View on GitHub (pinned to 157c9d86ac)
Solutions
- Validate each proto entry's key_data is non-null/32 bytes before calling toKey
- Re-download the exposure key export file and verify its signature/checksum
- Skip or log entries with missing key_data instead of propagating the exception
- Verify the export was fully downloaded (file size / completion) before parsing
Example fix
// before
private fun TemporaryExposureKeyProto.toKey() = Builder().setKeyData(key_data?.toByteArray() ?: throw IllegalArgumentException("key data missing"))...
// after
fun TemporaryExposureKeyProto.toKeyOrNull(): TemporaryExposureKey? {
val data = key_data?.toByteArray() ?: return null
return TemporaryExposureKey.TemporaryExposureKeyBuilder().setKeyData(data)
.setRollingStartIntervalNumber(rolling_start_interval_number ?: return null)
.setRollingPeriod(rolling_period ?: return null)
.setTransmissionRiskLevel(transmission_risk_level ?: 0).build()
} Defensive patterns
Strategy: validation
Validate before calling
fun TemporaryExposureKeyProto.hasRequiredFields(): Boolean =
key_data != null && key_data.size() > 0 &&
rolling_start_interval_number != null &&
rolling_period != null 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()
use(key)
} catch (e: IllegalArgumentException) {
Log.w(TAG, "Skipping malformed exposure key: ${e.message}")
} Prevention
- Validate export ZIP entries before converting (required fields present, key_data 16/32 bytes)
- Verify export file signature and checksum before parsing
- Skip-and-log malformed entries instead of failing the whole batch
- Ensure the diagnosis server emits spec-compliant ExposureKey exports
When it happens
Trigger: A key file (ZIP of exported exposure keys) contains a TemporaryExposureKey proto entry with key_data unset or empty; a malformed export is downloaded and parsed, then toKey() is invoked on each entry.
Common situations: Corrupt or truncated exposure-key export files; keys downloaded over a flaky connection and partially written; manually constructed or test protos missing key_data; mismatched export format versions.
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
- rolling start interval number missing
- rolling period 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/c01f895189584589.
Report an issue: GitHub.