dotnet/aspnetcore · error · IllegalArgumentException

Expected either 'error' or 'result' to be provided, but not

Error message

Expected either 'error' or 'result' to be provided, but not both.

What it means

CompletionMessage's constructor enforces the hub protocol invariant that a completion carries either an error or a result, but never both. Passing both non-null is contradictory (success vs failure) and would violate the wire contract.

Source

Thrown at src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/CompletionMessage.java:20

// The .NET Foundation licenses this file to you under the MIT license.

package com.microsoft.signalr;

import java.util.Map;

public final class CompletionMessage extends HubMessage {
    private final int type = HubMessageType.COMPLETION.value;
    private Map<String, String> headers;
    private final String invocationId;
    private final Object result;
    private final String error;

    public CompletionMessage(Map<String, String> headers, String invocationId, Object result, String error) {
        if (headers != null && !headers.isEmpty()) {
            this.headers = headers;
        }
        if (error != null && result != null) {
            throw new IllegalArgumentException("Expected either 'error' or 'result' to be provided, but not both.");
        }
        this.invocationId = invocationId;
        this.result = result;
        this.error = error;
    }

    public Map<String, String> getHeaders() {
        return headers;
    }

    public Object getResult() {
        return result;
    }

    public String getError() {
        return error;
    }

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Pass exactly one of result or error; leave the other null.
  2. Centralize CompletionMessage construction in a factory that enforces the invariant.
  3. Add an assertion in your builder so both-non-null fails earlier with a clearer message.
  4. If you need to represent 'result with warning', put the warning elsewhere (e.g. headers), not in error.

Example fix

// before
new CompletionMessage(null, invocationId, result, "warn"); // both set

// after
new CompletionMessage(null, invocationId, result, null);
Defensive patterns

Strategy: validation

Validate before calling

static CompletionMessage build(String id, Object result, String error) {
  if (result != null && error != null) {
    throw new IllegalArgumentException("Provide result OR error, not both");
  }
  return new CompletionMessage(null, id, result, error);
}

Prevention

When it happens

Trigger: Constructing CompletionMessage manually with both error and result non-null, typically in tests, custom protocol layers, or hand-built message factories.

Common situations: Unit tests building fixtures incorrectly, a custom hub/protocol wrapper that sets both fields, or copy-paste leaving a stale error alongside a result.

Related errors


AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06). Data as JSON: /api/errors/48636df05c0d5089. Report an issue: GitHub.