{"record":{"id":"3a0f251a7f44ad57","repo":"grpc/grpc-java","slug":"counter-has-overflowed","errorCode":null,"errorMessage":"Counter has overflowed.","messagePattern":"Counter has overflowed\\.","errorType":"exception","errorClass":"GeneralSecurityException","httpStatus":null,"severity":"error","filePath":"alts/src/main/java/io/grpc/alts/internal/AltsChannelCrypter.java","lineNumber":140,"sourceCode":"  public void destroy() {\n    // no destroy required\n  }\n\n  /** Increments {@code counter}, store the unincremented value in {@code oldCounter}. */\n  static void incrementCounter(byte[] counter, byte[] oldCounter) throws GeneralSecurityException {\n    System.arraycopy(counter, 0, oldCounter, 0, counter.length);\n    int i = 0;\n    for (; i < COUNTER_OVERFLOW_LENGTH; i++) {\n      counter[i]++;\n      if (counter[i] != (byte) 0x00) {\n        break;\n      }\n    }\n\n    if (i == COUNTER_OVERFLOW_LENGTH) {\n      // Restore old counter value to ensure that encrypt and decrypt keep failing.\n      System.arraycopy(oldCounter, 0, counter, 0, counter.length);\n      throw new GeneralSecurityException(\"Counter has overflowed.\");\n    }\n  }\n\n  /** Increments the input counter, returning the previous (unincremented) value. */\n  private byte[] incrementInCounter() throws GeneralSecurityException {\n    incrementCounter(inCounter, oldCounter);\n    return oldCounter;\n  }\n\n  /** Increments the output counter, returning the previous (unincremented) value. */\n  private byte[] incrementOutCounter() throws GeneralSecurityException {\n    incrementCounter(outCounter, oldCounter);\n    return oldCounter;\n  }\n\n  @VisibleForTesting\n  void incrementInCounterForTesting(int n) throws GeneralSecurityException {\n    for (int i = 0; i < n; i++) {","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/alts/src/main/java/io/grpc/alts/internal/AltsChannelCrypter.java#L122-L158","documentation":"ALTS message encryption uses a sequence counter that must never repeat. When incrementCounter() detects the counter reaching its overflow length (all bytes already at max via carry propagation), it restores the old counter value and throws GeneralSecurityException so encrypt/decrypt keep failing rather than reusing a counter value — which would break the confidentiality/integrity guarantees of the AEAD key.","triggerScenarios":"Sending or receiving more than 2^64 (per the counter layout) ALTS frames on a single channel: encrypting the next message or decrypting an incoming frame triggers the overflow check in incrementInCounter()/incrementOutCounter().","commonSituations":"An extremely long-lived, high-throughput ALTS channel that processes the maximum frame count; practically unreachable in normal workloads but possible on persistent bulk-data connections.","solutions":["Close and re-establish the ALTS channel (new handshake generates fresh keys and counters)","Catch GeneralSecurityException on the channel and treat it as terminal — the channel is unusable after overflow","Reduce per-connection data volume or add application-level channel recycling for very long-lived connections"],"exampleFix":"// before\n// keep using one channel forever; encrypt() eventually throws\n// after\ntry {\n  encrypt(frame);\n} catch (GeneralSecurityException e) {\n  channel.shutdownNow(); // rebuild channel with fresh handshake\n  channel = createAltsChannel();\n}","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"try {\n  encrypt(frame);\n} catch (GeneralSecurityException e) {\n  channel.shutdownNow();\n  channel = rebuildAltsChannel(); // fresh keys and counters\n}","preventionTips":["Treat GeneralSecurityException from an ALTS channel as terminal — never retry on the same channel","Recycle very long-lived high-throughput ALTS connections","Keep grpc-alts updated with counter-overflow fixes"],"tags":["grpc","alts","crypto","security","counter-overflow"],"backgroundTag":"internal-invariant-violation","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}