{"record":{"id":"555a8f1025ae4951","repo":"floci-io/floci","slug":"badrequestexception-555a8f","errorCode":"BadRequestException","errorMessage":"A GraphQL API name is required","messagePattern":"A GraphQL API name is required","errorType":"validation","errorClass":"AwsException","httpStatus":400,"severity":"error","filePath":"src/main/java/io/github/hectorvent/floci/services/appsync/AppSyncService.java","lineNumber":76,"sourceCode":"        this.typeStore = storageFactory.create(\"appsync\", \"appsync-types.json\", new TypeReference<>() {});\n        this.domainStore = storageFactory.create(\"appsync\", \"appsync-domainnames.json\", new TypeReference<>() {});\n        this.associationStore = storageFactory.create(\"appsync\", \"appsync-associations.json\", new TypeReference<>() {});\n        this.channelNamespaceStore = storageFactory.create(\"appsync\", \"appsync-channelnamespaces.json\", new TypeReference<>() {});\n        this.mergedApiAssociationStore = storageFactory.create(\"appsync\", \"appsync-merged-api-associations.json\", new TypeReference<>() {});\n        this.regionResolver = regionResolver;\n        this.schemaRegistry = schemaRegistry;\n        this.schemaCreationWorker = schemaCreationWorker;\n        this.requestContextInstance = requestContextInstance;\n        this.objectMapper = objectMapper;\n    }\n\n    // ──────────────────────────── GraphQL API ────────────────────────────\n\n    public GraphqlApi createGraphqlApi(Map<String, Object> request, String region) {\n        assertNoSchemaBusyAnywhere();\n        String name = (String) request.get(\"name\");\n        if (name == null || name.isBlank()) {\n            throw new AwsException(\"BadRequestException\", \"A GraphQL API name is required\", 400);\n        }\n        String authType = (String) request.get(\"authenticationType\");\n        if (authType == null || authType.isBlank()) {\n            throw new AwsException(\"BadRequestException\", \"The authenticationType is required\", 400);\n        }\n        String apiId = generateApiId();\n        GraphqlApi api = new GraphqlApi();\n        api.setApiId(apiId);\n        api.setName(name);\n        api.setAuthenticationType(parseEnum(AuthenticationType.class, authType));\n        Object xrayValue = request.get(\"xrayEnabled\");\n        if (xrayValue instanceof Boolean b) {\n            api.setXrayEnabled(b);\n        } else if (xrayValue instanceof String s) {\n            api.setXrayEnabled(Boolean.parseBoolean(s));\n        } else {\n            api.setXrayEnabled(false);\n        }","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/floci-io/floci/blob/62ff490619e7bd3554597c28c704081b4c15add5/src/main/java/io/github/hectorvent/floci/services/appsync/AppSyncService.java#L58-L94","documentation":"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.","triggerScenarios":"POST /v1/apis with a JSON body lacking 'name' (e.g. only authenticationType set); name key spelled 'Name' or 'apiName'; empty string name.","commonSituations":"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.","solutions":["Include a non-empty 'name' string in the CreateGraphqlApi request body.","If using the AWS SDK, the builder enforces this client-side in newer versions — keep it enabled rather than bypassing validation.","Validate request payloads against the AppSync CreateGraphqlApi schema before forwarding."],"exampleFix":"// before\nappSync.createGraphqlApi(b -> b.authenticationType(AuthenticationType.API_KEY)); // no name\n\n// after\nappSync.createGraphqlApi(b -> b.name(\"MyApi\")\n        .authenticationType(AuthenticationType.API_KEY));","handlingStrategy":"validation","validationCode":"if (request.get(\"name\") == null || ((String) request.get(\"name\")).isBlank()) {\n    throw new IllegalArgumentException(\"GraphqlApi 'name' is required\");\n}\nappSyncClient.createGraphqlApi(request);","typeGuard":"boolean isCreateApiRequestValid(Map<String, Object> req) {\n    return req.get(\"name\") instanceof String s && !s.isBlank();\n}","tryCatchPattern":"try {\n    appSync.createGraphqlApi(req);\n} catch (BadRequestException e) {\n    if (e.getMessage().contains(\"name is required\")) {\n        // populate name and retry\n    }\n    throw e;\n}","preventionTips":["Validate AppSync request maps at the edge before forwarding to the SDK.","Keep template files for CreateGraphqlApi with both name and authenticationType pre-filled."],"tags":["aws","appsync","validation","create-graphql-api"],"backgroundTag":null,"analyzedSha":"62ff490619e7bd3554597c28c704081b4c15add5","analyzedAt":"2026-08-14T14:25:23.764Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}