floci-io/floci · error · AwsException

NamespaceAlreadyExists

NamespaceAlreadyExists

Error message

A namespace named \"{}\" already exists.

What it means

Cloud Map namespace names must be unique within a region. Before creating a namespace, Floci scans existing namespaces for the same region + name pair and throws NamespaceAlreadyExists (HTTP 400) with a message naming the duplicate. This fires across all namespace types (DNS_PUBLIC, DNS_PRIVATE, HTTP) because the check lives in the shared newNamespace helper.

Source

Thrown at src/main/java/io/github/hectorvent/floci/services/cloudmap/CloudMapService.java:111

        if (vpc == null || vpc.isBlank()) {
            throw new AwsException("InvalidInput", "Vpc is required for a private DNS namespace.", 400);
        }
        Namespace ns = newNamespace(name, "DNS_PRIVATE", description, creatorRequestId, tags, region);
        ns.setVpc(vpc);
        ns.setHostedZoneId(generateHostedZoneId());
        namespaceStore.put(ns.getId(), ns);
        return submitOperation("CREATE_NAMESPACE", "NAMESPACE", ns.getId(), region);
    }

    private Namespace newNamespace(String name, String type, String description,
                                   String creatorRequestId, Map<String, String> tags, String region) {
        if (name == null || name.isBlank()) {
            throw new AwsException("InvalidInput", "Namespace name is required.", 400);
        }
        boolean exists = scan(namespaceStore).stream()
                .anyMatch(n -> region.equals(n.getRegion()) && name.equals(n.getName()));
        if (exists) {
            throw new AwsException("NamespaceAlreadyExists",
                    "A namespace named \"" + name + "\" already exists.", 400);
        }
        Namespace ns = new Namespace();
        ns.setId("ns-" + randomId(20));
        ns.setName(name);
        ns.setType(type);
        ns.setDescription(description);
        ns.setCreatorRequestId(creatorRequestId != null ? creatorRequestId : UUID.randomUUID().toString());
        ns.setCreateDate(Instant.now());
        ns.setRegion(region);
        ns.setServiceCount(0);
        if (tags != null) {
            ns.setTags(tags);
        }
        ns.setArn(regionResolver.buildArn("servicediscovery", region, "namespace/" + ns.getId()));
        return ns;
    }

View on GitHub (pinned to 62ff490619)

Solutions

  1. Check ListNamespaces for the name in that region first and reuse the existing namespace if present
  2. Catch NamespaceAlreadyExists and treat it as success in idempotent bootstrap code
  3. If duplicate names are legitimate, disambiguate the name per environment (e.g. app.prod.internal vs app.dev.internal)

Example fix

// before
cloudMapClient.createPrivateDnsNamespace(r -> r
    .name("app.internal")
    .vpc(vpcId)); // throws on second run

// after
boolean exists = cloudMapClient.listNamespaces().namespaces().stream()
    .anyMatch(n -> "app.internal".equals(n.name()));
if (!exists) {
    cloudMapClient.createPrivateDnsNamespace(r -> r
        .name("app.internal")
        .vpc(vpcId));
}
Defensive patterns

Strategy: try-catch

Validate before calling

boolean exists = cloudMapClient.listNamespaces().namespaces().stream()
    .anyMatch(n -> name.equals(n.name()));
if (exists) {
    // reuse the existing namespace instead of creating a new one
}

Try / catch

try {
    cloudMapClient.createPrivateDnsNamespace(r -> r.name(name).vpc(vpcId));
} catch (ServiceDiscoveryException e) {
    if ("NamespaceAlreadyExists".equals(e.awsErrorDetails().errorCode())) {
        // idempotent bootstrap: find and reuse the existing namespace
    } else { throw e; }
}

Prevention

When it happens

Trigger: Running CreatePublicDnsNamespace/CreatePrivateDnsNamespace/CreateHttpNamespace twice with the same Name in the same region without a distinct CreatorRequestId; re-running a bootstrap script that is not idempotent.

Common situations: Provisioning scripts run twice; CI pipelines that create namespaces per run with a fixed name; two services claiming the same domain name. Note AWS treats identical CreatorRequestId as idempotent, but Floci's duplicate check fires on the name alone.

Related errors


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