eclipse-vertx/vert.x · error · IllegalStateException

Invalid configuration

Error message

Invalid configuration

What it means

DefaultSslContextFactory.create() throws IllegalStateException when the factory has not been configured as either a client or a server factory (forClient == forServer). A factory can only build an SSLContext for one side of the connection, so using the factory without initializing it via a client/server setup path is an invalid configuration. This is a programming error, not an SSL/TLS handshake failure.

Source

Thrown at vertx-core/src/main/java/io/vertx/core/spi/tls/DefaultSslContextFactory.java:104

    return this;
  }

  @Override
  public SslContextFactory keyMananagerFactory(KeyManagerFactory kmf) {
    this.kmf = kmf;
    return this;
  }

  @Override
  public SslContextFactory trustManagerFactory(TrustManagerFactory tmf) {
    this.tmf = tmf;
    return this;
  }

  @Override
  public SslContext create() throws SSLException {
    if (forClient == forServer) {
      throw new IllegalStateException("Invalid configuration");
    }
    return createContext(useAlpn, forClient, kmf, tmf);
  }

  @Override
  public SslContextFactory enabledCipherSuites(Set<String> enabledCipherSuites) {
    this.enabledCipherSuites = enabledCipherSuites;
    return this;
  }

  @Override
  public SslContextFactory applicationProtocols(List<String> applicationProtocols) {
    this.applicationProtocols = applicationProtocols;
    return this;
  }

  /*
        If you don't specify a trust store, and you haven't set system properties, the system will try to use either a file

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Initialize the factory for a role before creating the context: use the factory's client configuration (forClient=true) when dialing out or server configuration (forServer=true) when binding a server.
  2. Prefer the high-level Vert.x API (HttpServerOptions/HttpClientOptions with KeyCertOptions/TrustOptions) which configures the factory correctly; only build SslContextFactory manually when truly needed.
  3. Fix the setup code path so create() is called exactly once, after role configuration.

Example fix

// before
SslContextFactory factory = new DefaultSslContextFactory();
SslContext ctx = factory.create(); // IllegalStateException
// after
SslContextFactory factory = new DefaultSslContextFactory();
factory.client(); // or factory.server()
SslContext ctx = factory.create();
Defensive patterns

Strategy: validation

Validate before calling

if (factory instanceof DefaultSslContextFactory) { /* ensure role set */ }
// Prefer: build via client()/server() options rather than raw factory; assert role before create
boolean configured = /* role initialized via client()/server() */;
if (!configured) throw new IllegalStateException("Set client or server role before create()");

Type guard

boolean isConfigured(SslContextFactory f) { return f != null && (f.isClient() ^ f.isServer()); }

Try / catch

try { SslContext ctx = factory.create(); } catch (IllegalStateException e) { log.error("SSL factory used without client/server role", e); }

Prevention

When it happens

Trigger: Calling SslContextFactory.create() on a DefaultSslContextFactory that was never initialized with a client or server role, e.g. using the raw factory without going through SslContextFactory.client()/server() style configuration so forClient and forServer are both false (or both true, which cannot happen through normal APIs).

Common situations: Custom TLS setup code that constructs a DefaultSslContextFactory directly and forgets to call the client()/server() initializer; refactoring code that dropped the client/server configuration call; wiring a factory in DI without its role.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06). Data as JSON: /api/errors/093885587d1dd7a2. Report an issue: GitHub.