floci-io/floci · error · AwsException

InvalidArgument

InvalidArgument

Error message

The alias must not be empty.

What it means

Thrown by Floci's CloudFront emulator when AssociateAlias is called with an alias that is null, empty, or whitespace-only. The service validates the alias string before touching distribution state, mirroring AWS CloudFront's InvalidArgument (HTTP 400) for a missing CNAME. It fails fast: no alias bookkeeping is modified when this fires.

Source

Thrown at src/main/java/io/github/hectorvent/floci/services/cloudfront/CloudFrontService.java:205

        if (marker != null && !marker.isEmpty()) {
            int idx = 0;
            for (int i = 0; i < all.size(); i++) {
                if (all.get(i).getId().equals(marker)) {
                    idx = i + 1;
                    break;
                }
            }
            all = all.subList(idx, all.size());
        }
        if (maxItems > 0 && all.size() > maxItems) {
            return all.subList(0, maxItems);
        }
        return all;
    }

    public synchronized void associateAlias(String targetDistributionId, String alias) {
        if (alias == null || alias.isBlank()) {
            throw new AwsException("InvalidArgument", "The alias must not be empty.", 400);
        }
        Distribution dist = getDistribution(targetDistributionId);
        if (dist.getConfig() == null) {
            throw new AwsException("InvalidArgument", "The target distribution has no configuration.", 400);
        }
        for (Distribution candidate : distStore.scan(k -> true)) {
            if (targetDistributionId.equals(candidate.getId()) || candidate.getConfig() == null
                    || candidate.getConfig().getAliases() == null) {
                continue;
            }
            List<String> previousAliases = candidate.getConfig().getAliases();
            List<String> remaining = new ArrayList<>(previousAliases);
            remaining.removeIf(existing -> alias.equalsIgnoreCase(existing));
            if (remaining.size() != previousAliases.size()) {
                candidate.getConfig().setAliases(remaining);
                candidate.setEtag(UUID.randomUUID().toString());
                candidate.setLastModifiedTime(Instant.now());
                distStore.put(candidate.getId(), candidate);

View on GitHub (pinned to 62ff490619)

Solutions

  1. Check the alias is non-null and non-blank before calling associateAlias (e.g. Objects.requireNonNull + isBlank guard).
  2. Trace where the alias value originates (env var, config, CLI arg) and fix the unset/blank source.
  3. If the value arrives from user input, validate and reject it at your API boundary with a clear message instead of relying on the 400.

Example fix

// before
cloudFrontService.associateAlias(distId, System.getenv("CF_ALIAS")); // may be null

// after
String alias = System.getenv("CF_ALIAS");
if (alias == null || alias.isBlank()) {
    throw new IllegalArgumentException("CF_ALIAS must be set to a CNAME like www.example.com");
}
cloudFrontService.associateAlias(distId, alias);
Defensive patterns

Strategy: validation

Validate before calling

boolean isAssociateableAlias(String alias) {
    return alias != null && !alias.isBlank() && alias.matches("(\\w[-_\\w]*\\.)+[a-zA-Z]{2,}");
}

Prevention

When it happens

Trigger: Calling associateAlias(targetDistributionId, alias) on CloudFrontService where alias == null, alias.isEmpty(), or alias is only whitespace. Via the wire this maps to an AssociateAlias request whose CNAME field was omitted or sent blank.

Common situations: Building the alias from an environment variable or config key that is unset in one environment; a templating layer that renders an empty string; passing the wrong variable (e.g. the distribution ID) into the alias parameter.

Related errors


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