{"record":{"id":"2d38c6c386c24bac","repo":"grpc/grpc-java","slug":"encountered-error-during-serialized-access","errorCode":null,"errorMessage":"Encountered error during serialized access","messagePattern":"Encountered error during serialized access","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"util/src/main/java/io/grpc/util/TransmitStatusRuntimeExceptionInterceptor.java","lineNumber":188,"sourceCode":"            SerializingServerCall.super.close(status, trailers);\n          }\n        }\n      });\n    }\n\n    @Override\n    public boolean isReady() {\n      final SettableFuture<Boolean> retVal = SettableFuture.create();\n      serializingExecutor.execute(new Runnable() {\n        @Override\n        public void run() {\n          retVal.set(SerializingServerCall.super.isReady());\n        }\n      });\n      try {\n        return retVal.get();\n      } catch (InterruptedException e) {\n        throw new RuntimeException(ERROR_MSG, e);\n      } catch (ExecutionException e) {\n        throw new RuntimeException(ERROR_MSG, e);\n      }\n    }\n\n    @Override\n    public boolean isCancelled() {\n      final SettableFuture<Boolean> retVal = SettableFuture.create();\n      serializingExecutor.execute(new Runnable() {\n        @Override\n        public void run() {\n          retVal.set(SerializingServerCall.super.isCancelled());\n        }\n      });\n      try {\n        return retVal.get();\n      } catch (InterruptedException e) {\n        throw new RuntimeException(ERROR_MSG, e);","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/util/src/main/java/io/grpc/util/TransmitStatusRuntimeExceptionInterceptor.java#L170-L206","documentation":"SerializingServerCall (installed by TransmitStatusRuntimeExceptionInterceptor) moves every ServerCall method onto a single serializing executor and blocks the caller on a SettableFuture. If the delegated isReady() computation fails or the wait is interrupted, the original exception is wrapped in a RuntimeException with the fixed message 'Encountered error during serialized access'. It signals that an exception escaped the serialized execution of the call, not a gRPC protocol problem per se.","triggerScenarios":"Calling isReady() on a ServerCall wrapped by TransmitStatusRuntimeExceptionInterceptor.intercept() while the underlying delegate's isReady() throws (e.g., transport already closed/failed), or the current thread is interrupted while waiting for the serializing executor to run the task.","commonSituations":"Server transport torn down concurrently while a service implementation checks call.isReady(); deadlocks or executor shutdown causing ExecutionException; spurious thread interruption during shutdown of a gRPC server.","solutions":["Inspect the cause of the RuntimeException (getCause()): InterruptedException or ExecutionException reveals the underlying delegate failure.","Ensure the wrapped call is not used after the server/transport has been shut down; guard with isCancelled() and lifecycle checks.","Avoid interrupting gRPC server threads; if interruption is expected (shutdown), catch and restore the interrupt flag in your service code.","Verify the interceptor is only applied where responses must be serialized (transmitting StatusRuntimeException in trailers) and not to calls that fail on closed transports."],"exampleFix":"// before\nif (call.isReady()) { call.sendMessage(msg); }\n// after\ntry {\n  if (call.isReady()) { call.sendMessage(msg); }\n} catch (RuntimeException e) {\n  if (e.getCause() instanceof InterruptedException) {\n    Thread.currentThread().interrupt(); // restore interrupt status\n  } else {\n    throw e;\n  }\n}","handlingStrategy":"try-catch","validationCode":"// check call lifecycle before reading state\nif (call.isCancelled()) return;","typeGuard":"boolean isCallUsable(ServerCall<?,?> call) {\n  try { call.isCancelled(); return true; } catch (RuntimeException e) { return false; }\n}","tryCatchPattern":"try {\n  boolean ready = call.isReady();\n} catch (RuntimeException e) {\n  Throwable cause = e.getCause();\n  if (cause instanceof InterruptedException) {\n    Thread.currentThread().interrupt();\n  } // else: transport failure, abort the stream\n}","preventionTips":["Do not interrupt gRPC server handler threads; use Server.shutdown() for graceful teardown.","Avoid calling ServerCall methods from inside the serializing executor.","Capture call state early in the handler before transports can tear down.","Always unwrap getCause() to find the real failure."],"tags":["grpc","concurrency","executor","interrupted"],"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"}