floci-io/floci · error · AwsException

BadRequestException

BadRequestException

Error message

A GraphQL API name is required

What it means

Thrown by AppSyncService.createGraphqlApi when the request body has no 'name' field or a blank one. AWS requires a name for every GraphQL API; Floci rejects the create with BadRequestException (HTTP 400) before generating an API id. Note it fires after assertNoSchemaBusyAnywhere, so an in-flight schema creation fails earlier with ConcurrentModificationException.

Source

Thrown at src/main/java/io/github/hectorvent/floci/services/appsync/AppSyncService.java:76

        this.typeStore = storageFactory.create("appsync", "appsync-types.json", new TypeReference<>() {});
        this.domainStore = storageFactory.create("appsync", "appsync-domainnames.json", new TypeReference<>() {});
        this.associationStore = storageFactory.create("appsync", "appsync-associations.json", new TypeReference<>() {});
        this.channelNamespaceStore = storageFactory.create("appsync", "appsync-channelnamespaces.json", new TypeReference<>() {});
        this.mergedApiAssociationStore = storageFactory.create("appsync", "appsync-merged-api-associations.json", new TypeReference<>() {});
        this.regionResolver = regionResolver;
        this.schemaRegistry = schemaRegistry;
        this.schemaCreationWorker = schemaCreationWorker;
        this.requestContextInstance = requestContextInstance;
        this.objectMapper = objectMapper;
    }

    // ──────────────────────────── GraphQL API ────────────────────────────

    public GraphqlApi createGraphqlApi(Map<String, Object> request, String region) {
        assertNoSchemaBusyAnywhere();
        String name = (String) request.get("name");
        if (name == null || name.isBlank()) {
            throw new AwsException("BadRequestException", "A GraphQL API name is required", 400);
        }
        String authType = (String) request.get("authenticationType");
        if (authType == null || authType.isBlank()) {
            throw new AwsException("BadRequestException", "The authenticationType is required", 400);
        }
        String apiId = generateApiId();
        GraphqlApi api = new GraphqlApi();
        api.setApiId(apiId);
        api.setName(name);
        api.setAuthenticationType(parseEnum(AuthenticationType.class, authType));
        Object xrayValue = request.get("xrayEnabled");
        if (xrayValue instanceof Boolean b) {
            api.setXrayEnabled(b);
        } else if (xrayValue instanceof String s) {
            api.setXrayEnabled(Boolean.parseBoolean(s));
        } else {
            api.setXrayEnabled(false);
        }

View on GitHub (pinned to 62ff490619)

Solutions

  1. Include a non-empty 'name' string in the CreateGraphqlApi request body.
  2. If using the AWS SDK, the builder enforces this client-side in newer versions — keep it enabled rather than bypassing validation.
  3. Validate request payloads against the AppSync CreateGraphqlApi schema before forwarding.

Example fix

// before
appSync.createGraphqlApi(b -> b.authenticationType(AuthenticationType.API_KEY)); // no name

// after
appSync.createGraphqlApi(b -> b.name("MyApi")
        .authenticationType(AuthenticationType.API_KEY));
Defensive patterns

Strategy: validation

Validate before calling

if (request.get("name") == null || ((String) request.get("name")).isBlank()) {
    throw new IllegalArgumentException("GraphqlApi 'name' is required");
}
appSyncClient.createGraphqlApi(request);

Type guard

boolean isCreateApiRequestValid(Map<String, Object> req) {
    return req.get("name") instanceof String s && !s.isBlank();
}

Try / catch

try {
    appSync.createGraphqlApi(req);
} catch (BadRequestException e) {
    if (e.getMessage().contains("name is required")) {
        // populate name and retry
    }
    throw e;
}

Prevention

When it happens

Trigger: POST /v1/apis with a JSON body lacking 'name' (e.g. only authenticationType set); name key spelled 'Name' or 'apiName'; empty string name.

Common situations: Raw REST calls or Terraform/CDK templates with a missing name attribute; SDK builders where name is set conditionally; thin wrappers forwarding a partially populated map.

Understand the failure class

Background: BadRequestException (HTTP 400) — NestJS 'Bad Request' Errors: Why They Fire and How to Fix Them — this error's family across 4 libraries.

Related errors


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