floci-io/floci · error · RuntimeException
Failed to fetch CloudFormation template from ${url}: ${e.get
Error message
Failed to fetch CloudFormation template from ${url}: ${e.getMessage()} What it means
Thrown when CloudFormation cannot fetch a template specified via TemplateURL. Floci only resolves TemplateURL against its own S3 emulator (path-style or virtual-hosted-style URLs on the configured hostname); the fetched object is read with s3Service.getObject(bucket, key). Any failure (missing bucket/object, wrong host, unreadable content) is wrapped in a RuntimeException with the URL and the underlying message.
Source
Thrown at src/main/java/io/github/hectorvent/floci/services/cloudformation/CloudFormationService.java:1357
|| host.endsWith(".localhost"));
if (isVirtualHosted) {
bucket = host.split("\\.")[0];
key = path.startsWith("/") ? path.substring(1) : path;
} else {
// Path-style: /bucket/key
String rawPath = path.startsWith("/") ? path.substring(1) : path;
int slash = rawPath.indexOf('/');
bucket = slash > 0 ? rawPath.substring(0, slash) : rawPath;
key = slash > 0 ? rawPath.substring(slash + 1) : "";
}
try {
var obj = s3Service.getObject(bucket, key);
return new String(obj.getData());
} catch (Exception e) {
LOG.errorv("Failed to fetch CloudFormation template from {0}: {1}", url, e.getMessage());
throw new RuntimeException("Failed to fetch CloudFormation template from " + url + ": " + e.getMessage(), e);
}
}
private boolean isConfiguredVirtualHostedS3Host(String host) {
String suffix = config.hostname().orElse(EmbeddedDnsServer.DEFAULT_SUFFIX);
return hasBucketPrefixForSuffix(host, suffix);
}
private static boolean hasBucketPrefixForSuffix(String host, String suffix) {
if (host == null || suffix == null || suffix.isBlank()) {
return false;
}
String normalizedHost = host.toLowerCase(Locale.ROOT);
String normalizedSuffix = suffix.toLowerCase(Locale.ROOT);
return normalizedHost.length() > normalizedSuffix.length() + 1
&& normalizedHost.endsWith("." + normalizedSuffix);
}
View on GitHub (pinned to 62ff490619)
Solutions
- Verify the object exists in the emulator: aws --endpoint-url http://localhost:4566 s3 ls s3://<bucket>/<key> (run against Floci, not real AWS).
- Use a path-style URL against the emulator, e.g. http://localhost:4566/<bucket>/<key>, to rule out virtual-hosted hostname resolution issues.
- If you must use virtual-hosted style, confirm floci hostname config and that the embedded DNS server resolves <bucket>.<suffix> to the emulator.
- If the bucket was created in a previous run, check the storage mode (memory vs persistent) — a memory backend loses objects on restart; re-upload the template.
Example fix
# before aws --endpoint-url http://localhost:4566 cloudformation create-stack \ --stack-name s --template-url https://my-bucket.s3.amazonaws.com/template.yml # after aws --endpoint-url http://localhost:4566 s3 cp template.yml s3://my-bucket/template.yml aws --endpoint-url http://localhost:4566 cloudformation create-stack \ --stack-name s --template-url http://localhost:4566/my-bucket/template.yml
Defensive patterns
Strategy: validation
Validate before calling
// Before CreateStack with TemplateURL, confirm the object is readable in the emulator var obj = s3.getObject(b -> b.bucket(bucket).key(key)); // throws NoSuchKey if absent // and build a path-style URL the emulator definitely serves: String templateUrl = "http://localhost:4566/" + bucket + "/" + key;
Try / catch
catch (RuntimeException e) when creating the stack; inspect the message for "Failed to fetch CloudFormation template" and surface the underlying S3 cause (usually NoSuchKey) to the user instead of retrying — retrying without fixing the URL/object cannot succeed.
Prevention
- Upload the template to the emulator's S3 before referencing it
- Prefer path-style URLs (http://localhost:4566/bucket/key) over virtual-hosted style in emulator tests
- Run template upload and stack create in the same script so the object is guaranteed present
When it happens
Trigger: CreateStack / UpdateStack / CreateStackSet called with TemplateURL pointing at an S3 object that does not exist in the emulator's S3 storage, a URL whose host is not the emulator hostname (real S3, localhost with wrong port, https vs http mismatch), or a virtual-hosted-style URL whose suffix does not match floci hostname config.
Common situations: Templates written for real AWS (https://bucket.s3.amazonaws.com/key), S3 buckets created before persistence was enabled so the object is gone after restart, DNS/hostname misconfiguration where virtual-hosted-style URLs never match EmbeddedDnsServer.DEFAULT_SUFFIX, or a typo in the bucket/key path.
Related errors
- ValidationException
- ValidationException
- ResourceNotFoundException
- ValidationException
- UnsupportedOperationException
AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14).
Data as JSON: /api/errors/9a80b2eff3c7d00e.
Report an issue: GitHub.