conductor-oss/conductor · critical · IllegalStateException

Each conductor.file-storage.conductor.signing.keys entry req

Error message

Each conductor.file-storage.conductor.signing.keys entry requires id and secret

What it means

Thrown by SigningProperties.validate() when signing is enabled and a key entry is null or has a blank id or blank secret. Each signing key must carry a non-blank id and a non-blank secret. Raised at startup as IllegalStateException, failing context initialization.

Source

Thrown at core/src/main/java/org/conductoross/conductor/core/storage/ConductorFileStorageProperties.java:116

        @AssertTrue(message = "at least one signing key is required when signing is enabled")
        public boolean isValid() {
            return !enabled || (keys != null && !keys.isEmpty());
        }

        /** Throws a startup-friendly error for unusable key configuration. */
        public void validate() {
            if (!enabled) {
                return;
            }
            if (keys == null || keys.isEmpty()) {
                throw new IllegalStateException(
                        "conductor.file-storage.conductor.signing.keys is required when signing is enabled");
            }
            Set<String> ids = new HashSet<>();
            for (Key key : keys) {
                if (key == null || isBlank(key.getId()) || isBlank(key.getSecret())) {
                    throw new IllegalStateException(
                            "Each conductor.file-storage.conductor.signing.keys entry requires id and secret");
                }
                if (!ids.add(key.getId())) {
                    throw new IllegalStateException(
                            "conductor.file-storage.conductor.signing.keys contains duplicate id: "
                                    + key.getId());
                }
            }
        }

        private boolean isBlank(String value) {
            return value == null || value.isBlank();
        }
    }

    /** An ordered signing key. The first key signs new URLs; every key verifies existing URLs. */
    public static class Key {

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Ensure every keys entry has both a non-empty id and secret.
  2. Resolve the source env var/secret and confirm it is non-empty in the runtime environment.
  3. Use a secrets manager / devkey to inject the secret rather than hardcoding blanks.

Example fix

# before
signing:
  enabled: true
  keys:
    - id: key-1
      secret:    # blank -> startup failure

# after
signing:
  enabled: true
  keys:
    - id: key-1
      secret: ${SIGNING_KEY_SECRET}
Defensive patterns

Strategy: validation

Validate before calling

// Fail fast in a test:
for (Key k : props.getSigning().getKeys()) {
    org.junit.jupiter.api.Assertions.assertFalse(
        k.getId() == null || k.getId().isBlank() || k.getSecret() == null || k.getSecret().isBlank());
}

Prevention

When it happens

Trigger: A keys entry with missing id, missing secret, or whitespace-only values, while conductor.file-storage.conductor.signing.enabled=true. For example a key with id set via an env var that resolves to empty.

Common situations: Secret supplied through an environment variable that is unset in the deployment; YAML key list with a placeholder that was never substituted; partial key object copied from docs with secret left blank.

Related errors


AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14). Data as JSON: /api/errors/0a03a4a6079c7bcf. Report an issue: GitHub.