floci-io/floci · error · AppSyncTransportException

BadRequestException

BadRequestException

Error message

Missing operation name.

What it means

A GraphQL execution request contained more than one operation definition (multiple anonymous or named operations) but no operationName was supplied, so the executor cannot know which one to run. Floci's QueryExecutor raises HTTP 400 BadRequestException 'Missing operation name.', matching AppSync's behavior for ambiguous documents.

Source

Thrown at src/main/java/io/github/hectorvent/floci/services/appsync/graphql/QueryExecutor.java:40

public class QueryExecutor {

    private final AppSyncErrorFormatter formatter;

    @Inject
    public QueryExecutor(AppSyncErrorFormatter formatter) {
        this.formatter = formatter;
    }

    public Map<String, Object> execute(GraphQLSchema schema, String query,
                                       Map<String, Object> variables, String operationName) {
        return execute(SchemaRegistry.buildGraphQL(schema), query, variables, operationName);
    }

    public Map<String, Object> execute(GraphQL graphQL, String query,
                                       Map<String, Object> variables, String operationName) {
        List<OperationDefinition> operations = parseOperations(query);
        if (operations.size() > 1 && (operationName == null || operationName.isBlank())) {
            throw new AppSyncTransportException(400, "BadRequestException",
                    AppSyncErrorFormatter.MSG_MISSING_OPERATION_NAME);
        }

        OperationDefinition selected = selectOperation(operations, operationName);
        if (selected != null && selected.getOperation() == OperationDefinition.Operation.SUBSCRIPTION) {
            ExecutionResult rejected = ExecutionResultImpl.newExecutionResult()
                    .addError(GraphqlErrorBuilder.newError()
                            .message("Subscriptions are not supported over HTTP")
                            .errorType(ErrorType.OperationNotSupported)
                            .build())
                    .build();
            return formatter.format(rejected);
        }

        ExecutionInput.Builder inputBuilder = ExecutionInput.newExecutionInput().query(query);
        if (variables != null) {
            inputBuilder.variables(variables);
        }

View on GitHub (pinned to 62ff490619)

Solutions

  1. Add "operationName": "NameOfOperation" matching one top-level operation in the document.
  2. Or split the document so the request contains exactly one operation.
  3. If a library builds the request for you, set its operation-name option (e.g. graphql-request/mutation function name).

Example fix

// before
fetch(url, { body: JSON.stringify({ query: 'query A { a } query B { b }' }) });

// after
fetch(url, { body: JSON.stringify({ query: 'query A { a } query B { b }', operationName: 'A' }) });
Defensive patterns

Strategy: validation

Validate before calling

const ops = [...query.matchAll(/\b(query|mutation|subscription)\s+([A-Za-z]\w*)/g)].map(m => m[2]);
const anon = /^\s*(query|mutation|subscription)?\s*[({]/m.test(query);
if (ops.length + (anon ? 1 : 0) > 1 && !operationName) throw new Error('operationName required');

Try / catch

catch (BadRequestException e) {
    if ("Missing operation name.".equals(e.getMessage())) { /* set operationName to the intended op and retry */ }
}

Prevention

When it happens

Trigger: POSTing a document like 'query A { ... } query B { ... }' or 'query { ... } mutation { ... }' with no operationName field; also an anonymous query plus a named mutation in one document. Conversely, a single-operation document needs no operationName.

Common situations: Concatenating query fragments for convenience; shipping whole schema test documents; code that composes queries from multiple templates without selecting one.

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/bb7c631540e284ee. Report an issue: GitHub.