floci-io/floci · error · IllegalStateException

TLS enabled but no certificate provided and self-signed gene

Error message

TLS enabled but no certificate provided and self-signed generation disabled. Set FLOCI_TLS_CERT_PATH + FLOCI_TLS_KEY_PATH, or enable FLOCI_TLS_SELF_SIGNED.

What it means

Thrown by PollForJobs when the actionTypeId.owner field in the request is not 'Custom' (or, for PollForThirdPartyJobs, not 'ThirdParty'). The emulator only queues custom-job polling for the matching owner category, mirroring AWS CodePipeline's rule that PollForJobs is reserved for Custom actions and PollForThirdPartyJobs for ThirdParty actions. The check happens before any job lookup, so the request fails fast with HTTP 400 ValidationException.

Source

Thrown at src/main/java/io/github/hectorvent/floci/config/TlsConfigSource.java:114

                
                // Regenerate when the hostname config changed, or when the existing certificate
                // is a legacy non-self-signed cert (issuer != subject) — those cannot serve as a
                // trust anchor for clients that install them, so an upgrade must replace them.
                if (hostnameConfigChanged(tlsDir, currentHostnames) || !isSelfSigned(certFile)) {
                    generateSelfSignedCert(tlsDir, certFile, keyFile);
                } else {
                    // Configuration unchanged - reuse existing certificate
                    LOG.infov("TLS: reusing existing self-signed certificate: {0}", certFile);
                }
            } else {
                // Certificate files don't exist - generate new certificate
                generateSelfSignedCert(tlsDir, certFile, keyFile);
            }

            certPath = certFile.toAbsolutePath().toString();
            keyPath = keyFile.toAbsolutePath().toString();
        } else {
            throw new IllegalStateException(
                    "TLS enabled but no certificate provided and self-signed generation disabled. "
                            + "Set FLOCI_TLS_CERT_PATH + FLOCI_TLS_KEY_PATH, or enable FLOCI_TLS_SELF_SIGNED.");
        }

        properties.put("quarkus.http.ssl.certificate.files", certPath);
        properties.put("quarkus.http.ssl.certificate.key-files", keyPath);
        // When TLS is enabled, Quarkus HTTP and HTTPS run on internal ports.
        // A TlsProxyServer (NetServer) listens on the public Floci port (4566)
        // and does protocol detection to route HTTP and HTTPS to the correct backend.
        properties.put("quarkus.http.insecure-requests", "enabled");
        properties.put("quarkus.http.host", "127.0.0.1");
        properties.put("quarkus.http.port", "4510");
        properties.put("quarkus.http.ssl-port", "4511");

        LOG.infov("TLS: HTTPS enabled — proxy will listen on port {0} (HTTP+HTTPS), cert={1}",
                resolveProperty("floci.port", "4566"), certPath);
    }

View on GitHub (pinned to 62ff490619)

Solutions

  1. Set actionTypeId.owner to 'Custom' when calling PollForJobs (and 'ThirdParty' for PollForThirdPartyJobs)
  2. Verify the category/provider/version triple also matches the ActionType you registered via PutActionType, since owner is only one part of the key
  3. Check the worker's configuration for which poll operation it invokes and align it with the owner your action declaration uses

Example fix

// before
ActionTypeId id = ActionTypeId.builder().category(ActionCategory.Deploy).owner("AWS").provider("MyProvider").version("1").build();
poller.pollForJobs(PollForJobsRequest.builder().actionTypeId(id).build());

// after
ActionTypeId id = ActionTypeId.builder().category(ActionCategory.Deploy).owner("Custom").provider("MyProvider").version("1").build();
poller.pollForJobs(PollForJobsRequest.builder().actionTypeId(id).build());
Defensive patterns

Strategy: validation

Validate before calling

String owner = request.actionTypeId().owner();
String expected = thirdParty ? "ThirdParty" : "Custom";
if (!expected.equals(owner)) {
    throw new IllegalArgumentException("PollForJobs owner must be " + expected + ", got: " + owner);
}

Prevention

When it happens

Trigger: Calling PollForJobs with actionTypeId.owner = 'AWS' or 'ThirdParty'; calling PollForThirdPartyJobs with owner = 'Custom' or 'AWS'; omitting the owner field entirely (path('owner').asText() returns "" which fails the equals check).

Common situations: A custom worker built for one action type pointed at the wrong poll endpoint; copy-pasting an actionTypeId from a pipeline that uses an AWS-managed provider; SDK models where owner defaults to something other than Custom.

Understand the failure class

Related errors


AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14). Data as JSON: /api/errors/b7810bc1566f687b. Report an issue: GitHub.