grpc/grpc-java · error · IOException
SocketFactory ${socketFactory} did not produce an SSLSocket:
Error message
SocketFactory ${socketFactory} did not produce an SSLSocket: ${s.getClass()} What it means
ClientCertRequestingSocketFactory (and related wrapper) wraps a base SSLSocketFactory but requires the sockets it produces to actually be SSLSocket instances so client-auth and protocol settings can be applied. If the configured socket factory yields a plain socket, apply() throws IOException stating the factory did not produce an SSLSocket.
Source
Thrown at okhttp/src/main/java/io/grpc/okhttp/OkHttpServerBuilder.java:533
public static HandshakerSocketFactoryResult factory(HandshakerSocketFactory factory) {
return new HandshakerSocketFactoryResult(
Preconditions.checkNotNull(factory, "factory"), null);
}
}
static final class ClientCertRequestingSocketFactory extends SSLSocketFactory {
private final SSLSocketFactory socketFactory;
private final boolean required;
public ClientCertRequestingSocketFactory(SSLSocketFactory socketFactory, boolean required) {
this.socketFactory = Preconditions.checkNotNull(socketFactory, "socketFactory");
this.required = required;
}
private Socket apply(Socket s) throws IOException {
if (!(s instanceof SSLSocket)) {
throw new IOException(
"SocketFactory " + socketFactory + " did not produce an SSLSocket: " + s.getClass());
}
SSLSocket sslSocket = (SSLSocket) s;
if (required) {
sslSocket.setNeedClientAuth(true);
} else {
sslSocket.setWantClientAuth(true);
}
return sslSocket;
}
@Override public Socket createSocket(Socket s, String host, int port, boolean autoClose)
throws IOException {
return apply(socketFactory.createSocket(s, host, port, autoClose));
}
@Override public Socket createSocket(String host, int port) throws IOException {
return apply(socketFactory.createSocket(host, port));View on GitHub (pinned to 64daddc1f3)
Solutions
- Fix the custom SocketFactory so every createSocket overload returns an SSLSocket (typically obtained from an SSLContext's SSLSocketFactory)
- Alternatively use TlsServerCredentials.keyManager/trustManager and let gRPC build the SSL socket itself
- Log/inspect which factory instance is printed in the message to identify the faulty factory
Example fix
// before return new Socket(); // after return sslContext.getSocketFactory().createSocket(host, port);
Defensive patterns
Strategy: validation
Validate before calling
Socket test = mySocketFactory.createSocket();
if (!(test instanceof SSLSocket)) throw new IllegalStateException("Factory must return SSLSocket"); Type guard
function returnsSslSocket(f: javax.net.SocketFactory, s: Socket): boolean { return s instanceof javax.net.ssl.SSLSocket; } Try / catch
try { server.start(); }
catch (IOException e) {
if (e.getMessage().startsWith("SocketFactory ")) { /* fix custom factory to return SSLSocket */ }
} Prevention
- Have custom factories obtain sockets from SSLContext.getSocketFactory()
- Unit-test every createSocket overload of custom factories
- Prefer keyManager/trustManager over custom socket factories when possible
When it happens
Trigger: A custom javax.net.SocketFactory supplied via TlsServerCredentials.customSSLSocketFactory... style configuration returns a non-SSL Socket when createSocket is called during connection setup.
Common situations: Misconfigured custom socket factories, factories that delegate to the default factory but return a wrapped/plain socket, mocking or subclassing mistakes in test setups.
Related errors
- SocketFactory ${socketFactory} did not produce an SSLSocket:
- Can't set TLS settings for ALTS
- Unexpected error converting ChannelCredentials to Netty SslC
- Failed to build SSL context from certificate files: ${e}
- Failed to build SSL context from certificate streams: ${e}
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/366a874eb4a12ebc.
Report an issue: GitHub.