conductor-oss/conductor · error · IllegalStateException
File-storage URL signing is not enabled
Error message
File-storage URL signing is not enabled
What it means
Thrown by FileStorageUrlSigner.sign() when the signing feature flag is off. The signer bean is constructed regardless, but sign() is gated behind SigningProperties.isEnabled() because HMAC-signed content URLs are opt-in. The default value of conductor.file-storage.conductor.signing.enabled is false, so any code path that calls sign() without the operator turning signing on hits this IllegalStateException at runtime.
Source
Thrown at core/src/main/java/org/conductoross/conductor/core/storage/FileStorageUrlSigner.java:58
properties.validate();
this.keysById =
properties.getKeys().stream()
.collect(
Collectors.toUnmodifiableMap(
ConductorFileStorageProperties.Key::getId,
Function.identity()));
}
/** Signs a content request using the first configured key, the active key during rotation. */
public SignedUrl sign(
Operation operation,
String workflowId,
String fileId,
long expirationEpochSeconds,
String uploadId,
Integer partNumber) {
if (!properties.isEnabled()) {
throw new IllegalStateException("File-storage URL signing is not enabled");
}
ConductorFileStorageProperties.Key signingKey = properties.getKeys().get(0);
return new SignedUrl(
signingKey.getId(),
Base64.getUrlEncoder()
.withoutPadding()
.encodeToString(
hmac(
canonicalize(
operation,
workflowId,
fileId,
expirationEpochSeconds,
uploadId,
partNumber),
signingKey)));
}View on GitHub (pinned to cf7c3e4a8a)
Solutions
- Set conductor.file-storage.conductor.signing.enabled=true in application.yml (or the active profile) and supply at least one entry in conductor.file-storage.conductor.signing.keys with non-blank id and secret.
- Verify the YAML node path and indentation: the prefix is conductor.file-storage.conductor.signing.* (note the inner conductor segment), not conductor.file-storage.signing.*.
- If sign() is called from your own code, gate the call on the bound SigningProperties.isEnabled() (or properties.getSigning().isEnabled()) so the path is skipped when signing is intentionally disabled.
- Rebuild/restart the Spring context so @ConfigurationProperties rebinds; confirm no profile-specific file is shadowing the enabled flag with a later-loaded false.
- Add an integration test that asserts the signer bean is in the expected enabled state for the production profile to catch regressions.
Example fix
// before (application.yml)
conductor:
file-storage:
conductor:
signing:
keys:
- id: k1
secret: ${SIGNING_SECRET}
// after
conductor:
file-storage:
conductor:
signing:
enabled: true
keys:
- id: k1
secret: ${SIGNING_SECRET} Defensive patterns
Strategy: validation
Validate before calling
// Call this before FileStorageUrlSigner.sign(...)
import org.conductoross.conductor.core.storage.ConductorFileStorageProperties;
public boolean canSignUrls(ConductorFileStorageProperties.SigningProperties signing) {
return signing != null
&& signing.isEnabled()
&& signing.getKeys() != null
&& !signing.getKeys().isEmpty();
}
// usage
if (!canSignUrls(properties.getSigning())) {
// return an unsigned URL, or a 503 / feature-disabled response
} else {
SignedUrl signed = signer.sign(op, workflowId, fileId, exp, uploadId, partNumber);
} Try / catch
// Only when you cannot pre-validate (e.g. signer handed to you opaquely)
try {
SignedUrl signed = signer.sign(op, workflowId, fileId, exp, uploadId, partNumber);
} catch (IllegalStateException e) {
if ("File-storage URL signing is not enabled".equals(e.getMessage())) {
// feature is off: degrade gracefully (unsigned URL or 503), do NOT retry
log.warn("File-storage URL signing disabled; returning unsigned URL");
} else {
throw e; // a different IllegalStateException (e.g. error 481) — rethrow
}
} Prevention
- Bind ConductorFileStorageProperties into any component that calls sign() and assert getSigning().isEnabled() in a @PostConstruct self-check that fails fast.
- Keep the signing.enabled flag and the keys list in the same YAML block so one merge never enables signing without keys (the constructor's validate() will then fail at startup instead).
- Add a test profile that mirrors production's signing config so a missing enabled flag surfaces during the build rather than at runtime.
- Treat sign() as a privileged path: only the HTTP transfer controller should call it, and that controller should have an integration test asserting the enabled state.
When it happens
Trigger: Any invocation of FileStorageUrlSigner.sign(operation, workflowId, fileId, expirationEpochSeconds, uploadId, partNumber) while ConductorFileStorageProperties.SigningProperties.isEnabled() returns false. This happens when the HTTP transfer layer is wired to issue signed URLs but the conductor.file-storage.conductor.signing.enabled YAML property was left at its default (false) or explicitly set to false.
Common situations: Operator switched the file-storage backend to the Conductor-managed one and added signing.keys but forgot the enabled: true sibling; a Spring profile override (e.g. application-dev.yml) reset signing.enabled to false; YAML indentation placed keys under the wrong node so the enabled flag never bound; CI/test environment loads defaults and a test calls sign() directly without a test fixture flipping the flag.
Related errors
- Unable to sign file-storage URL
- Unsupported agent framework: '${framework}'. Supported frame
- Skill registry is not available
- llmProvider not specified: {name}
- no configuration found for: {name}
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/598fa9d74003f742.
Report an issue: GitHub.