{"record":{"id":"f2b9e108fd465688","repo":"microg/GmsCore","slug":"integrityerrorcode-nonce-too-long","errorCode":"IntegrityErrorCode.NONCE_TOO_LONG","errorMessage":"Nonce too long.","messagePattern":"Nonce too long\\.","errorType":"error_code","errorClass":"StandardIntegrityException","httpStatus":null,"severity":"error","filePath":"vending-app/src/main/kotlin/com/google/android/finsky/integrityservice/IntegrityService.kt","lineNumber":125,"sourceCode":"                    throw StandardIntegrityException(IntegrityErrorCode.INTERNAL_ERROR, \"Null packageName.\")\n                }\n                integrityData = callerAppToIntegrityData(context, packageName)\n                if (integrityData?.allowed != true) {\n                    throw StandardIntegrityException(IntegrityErrorCode.INTERNAL_ERROR, \"Not allowed to request integrity token.\")\n                }\n                val playIntegrityEnabled = VendingPreferences.isDeviceAttestationEnabled(context)\n                if (!playIntegrityEnabled) {\n                    throw StandardIntegrityException(IntegrityErrorCode.INTERNAL_ERROR, \"API is disabled.\")\n                }\n                val nonceArr = request.getByteArray(KEY_NONCE)\n                if (nonceArr == null) {\n                    throw StandardIntegrityException(IntegrityErrorCode.INTERNAL_ERROR, \"Nonce missing.\")\n                }\n                if (nonceArr.size < 16) {\n                    throw StandardIntegrityException(IntegrityErrorCode.NONCE_TOO_SHORT, \"Nonce too short.\")\n                }\n                if (nonceArr.size >= 500) {\n                    throw StandardIntegrityException(IntegrityErrorCode.NONCE_TOO_LONG, \"Nonce too long.\")\n                }\n                val cloudProjectNumber = request.getLong(KEY_CLOUD_PROJECT, 0L)\n                val playCoreVersion = request.getPlayCoreVersion()\n                Log.d(TAG, \"requestIntegrityToken(packageName: $packageName, nonce: ${nonceArr.encodeBase64(false)}, cloudProjectNumber: $cloudProjectNumber, playCoreVersion: $playCoreVersion)\")\n\n                val packageInfo = context.packageManager.getPackageInfoCompat(packageName, SIGNING_FLAGS)\n                val timestamp = makeTimestamp(System.currentTimeMillis())\n                val versionCode = packageInfo.versionCode\n\n                val integrityParams = IntegrityParams(\n                    packageName = PackageNameWrapper(packageName),\n                    versionCode = VersionCodeWrapper(versionCode),\n                    nonce = nonceArr.encodeBase64(noPadding = false, noWrap = true, urlSafe = true),\n                    certificateSha256Digests = packageInfo.signaturesCompat.map {\n                        it.toByteArray().sha256().encodeBase64(noPadding = true, noWrap = true, urlSafe = true)\n                    },\n                    timestampAtRequest = timestamp,\n                    cloudProjectNumber = cloudProjectNumber.takeIf { it > 0L }","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/vending-app/src/main/kotlin/com/google/android/finsky/integrityservice/IntegrityService.kt#L107-L143","documentation":"The nonce byte array supplied to requestIntegrityToken is 500 bytes or larger, exceeding the service's maximum. The nonce is embedded in the signed response, so oversized values are rejected with IntegrityErrorCode.NONCE_TOO_LONG.","triggerScenarios":"Calling requestIntegrityToken with a KEY_NONCE byte array whose size >= 500, e.g. serializing an entire request/response body, large JSON blob, or concatenated data into the nonce.","commonSituations":"Putting a full JSON document of request details into the nonce instead of a hash; appending debug/trace data; double-encoding (Base64 of Base64) inflating size; passing a whole file's bytes.","solutions":["Hash the large payload and use the digest as the nonce: MessageDigest.getInstance(\"SHA-256\").digest(payload) (32 bytes), storing the full payload server-side for comparison.","Check nonceArr.size < 500 at the call site before sending the request.","Remove unnecessary fields from the nonce payload; keep it to a compact, hashed summary.","Avoid redundant encodings (e.g. Base64-encoding an already-encoded string) that inflate byte size."],"exampleFix":"// before\nval nonce = buildJsonString(requestDetails).toByteArray() // can exceed 500 bytes\n// after\nval nonce = MessageDigest.getInstance(\"SHA-256\")\n    .digest(buildJsonString(requestDetails).toByteArray()) // 32 bytes\nserverNonceStore.store(expectedHash = nonce)","handlingStrategy":"validation","validationCode":"fun isNonceTooLong(nonce: ByteArray) = nonce.size >= 500\nif (isNonceTooLong(nonce)) nonce = MessageDigest.getInstance(\"SHA-256\").digest(nonce)","typeGuard":"fun ByteArray?.isNonceValid(): Boolean = this != null && size in 16..499","tryCatchPattern":"try {\n    integrityManager.requestIntegrityToken(request)\n} catch (e: StandardIntegrityException) {\n    if (e.errorCode == IntegrityErrorCode.NONCE_TOO_LONG) {\n        hashPayloadAndRetry()\n    } else throw e\n}","preventionTips":["Always hash large payloads (SHA-256) before using them as nonces","Keep nonce payloads compact; store large data server-side","Add a length assertion (size < 500) in the nonce helper"],"tags":["play-integrity","kotlin","android","nonce","payload-size"],"backgroundTag":"payload-too-large","analyzedSha":"157c9d86ac46c195a86c2f15ab55c84036223f95","analyzedAt":"2026-09-06T17:27:33.892Z","contentChangedAt":"2026-09-06T17:27:33.892Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}