Skip to content

[Bug]: TaskPushNotificationConfig.id is enforced as required, contradicting the spec where id is optional on create #1081

Description

@microedu202

What happened?

Summary

Per the A2A specification (Section 3.1.7, "Create Push Notification Config"), the id field of a push notification config is optional when creating one — the only required input is url, and the server assigns an ID if none is provided. The runtime request paths honor this, but the Java domain record TaskPushNotificationConfig enforces id as non-null, which contradicts the spec, the gRPC proto definition, and the store interface's own documented contract.

Spec reference

What the code does

Consistent with the spec

  • spec-grpc/src/main/proto/a2a.proto (message TaskPushNotificationConfig, lines 466–480): string id = 2; is not marked (google.api.field_behavior) = REQUIRED; only url is.
  • All request entry points (JSON-RPC JSONRPCUtils.java:224-230, REST RestHandler.java:376-385) parse the body into a proto builder first, so a missing id arrives as the protobuf default empty string "", and InMemoryPushNotificationConfigStore.setInfo (:51) defaults an empty id to the task ID (if (notificationConfig.id().isEmpty()) builder.id(taskId)). So a client omitting id does get a config back with an assigned ID.

Inconsistent with the spec

  • spec/src/main/java/org/a2aproject/sdk/spec/TaskPushNotificationConfig.java:
    • Compact constructor (line 48): Assert.checkNotNullParam("id", id);
    • Builder.build() (line 177): Assert.checkNotNullParam("id", id);

This makes id required at the domain-API level, so:

  1. TaskPushNotificationConfig.builder().url(...).build() throws IllegalArgumentException when id is omitted — but the spec says id is optional and the server assigns it.
  2. PushNotificationConfigStore.setInfo documents "If notificationConfig.id() is null or empty, it's set to the task ID" (PushNotificationConfigStore.java:91), but the null branch is dead code — a null id can never be constructed through the public API.
  3. InMemoryPushNotificationConfigStore.setInfo:51 calls notificationConfig.id().isEmpty(); if a null id ever reached it (as the Javadoc promises), it would NPE instead of defaulting.

The current "optional id works at runtime" behavior is load-bearing on the fact that the mapper TaskPushNotificationConfigMapper.fromProto does not apply emptyToNull to id (it does for taskId/token/tenant) — it only survives because proto yields "" rather than null.

Related (secondary) inconsistency

GetTaskPushNotificationConfigParams.java:31-32: the Javadoc describes id as "optional specific configuration ID to retrieve", but the constructor asserts checkNotNullParam("id", id) — so the default config cannot be retrieved without specifying an id.

Expected behavior

  • id should be optional when constructing/creating a TaskPushNotificationConfig; the server assigns an ID (e.g., defaults to the task ID) when it is absent, and returns the config with the assigned ID.
  • Constructing TaskPushNotificationConfig.builder().url(...).build() should succeed, mirroring the spec and the 0.3 compat record PushNotificationConfig_v0_3 (which only validates url).

Relevant log output

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions