Skip to content

Add Reactor NPE warning to sdk-java-content-response rule#42

Merged
TheovanKraay merged 3 commits into
mainfrom
copilot/fix-npe-reactive-streams
Mar 23, 2026
Merged

Add Reactor NPE warning to sdk-java-content-response rule#42
TheovanKraay merged 3 commits into
mainfrom
copilot/fix-npe-reactive-streams

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 23, 2026

SCOPE profile P08 found that contentResponseOnWriteEnabled(false) with CosmosAsyncClient causes NullPointerException deep in Reactor internals — getItem() returns null, which violates Reactive Streams Spec Rule 2.13 (no null signals). The existing rule's "When NOT to enable" section recommended false for high-throughput writes without warning about this.

Changes

  • Added ⚠️ Reactor warning section with incorrect/correct code examples showing the NPE cause and two safe alternatives
  • Scoped "When NOT to enable" to synchronous CosmosClient only
  • Updated Key Points to call out the Reactor constraint explicitly
  • Recompiled AGENTS.md via npm run build

Incorrect pattern (causes NPE)

CosmosAsyncClient asyncClient = new CosmosClientBuilder()
    .contentResponseOnWriteEnabled(false)
    .buildAsyncClient();

container.upsertItem(item)
    .map(CosmosItemResponse::getItem)  // getItem() returns null → NPE
    .block();

Safe alternatives

// Option 1: Keep content response enabled for async clients
.contentResponseOnWriteEnabled(true)

// Option 2: Guard against null if suppression is needed
container.upsertItem(item)
    .flatMap(response -> {
        MyItem result = response.getItem();
        return result != null ? Mono.just(result) : Mono.empty();
    });
Original prompt

This section details on the original issue you should resolve

<issue_title>contentResponseOnWriteEnabled(false) causes Reactor NPE in reactive streams</issue_title>
<issue_description>## Summary

When using CosmosAsyncClient with reactive streams (Project Reactor), setting contentResponseOnWriteEnabled(false) causes NullPointerException in .map(CosmosItemResponse::getItem) because Reactor does not allow null signals in its pipeline. The existing sdk-java-content-response rule covers the core guidance but does not warn about this Reactor-specific consequence.

SCOPE Observations

In the Java Gaming Leaderboard scenario, SCOPE profile P08 used the raw azure-cosmos SDK v4.57.0 with CosmosAsyncClient and reactive streams bridged to servlet via .block(). P08 did not have the Agent Kit installed.

Key findings:

  • The agent set contentResponseOnWriteEnabled(false) as a performance optimization to suppress response payloads on writes
  • This caused CosmosItemResponse.getItem() to return null, which is illegal in Reactor streams per the Reactive Streams Specification (Rule 2.13)
  • The NPE occurred deep in the stream pipeline — stack traces pointed to Reactor internals, not the Cosmos SDK setting, making diagnosis difficult
  • The existing sdk-java-content-response rule recommends contentResponseOnWriteEnabled(true) as the default, which would have prevented the NPE in isolation. However, the same rule's "When NOT to enable" section recommends false for high-throughput write workloads — without warning about the Reactor null-signal violation this causes

Remediation Applied

During emulator-based runtime testing, the following was done to fix the reactive stream NPE:

  1. Changed contentResponseOnWriteEnabled(false) to contentResponseOnWriteEnabled(true) — resolved the NPE by ensuring getItem() returns a non-null value
  2. Fixed downstream switchIfEmpty patterns that were also affected by null signals in the reactive pipeline
  3. Verified all 5 API endpoints — POST /api/v1/scores returned 201 Created, player profiles created correctly, rank queries returned correct rankings

Evidence

Incorrect Pattern

// ❌ Causes NPE in reactive stream
CosmosClientBuilder builder = new CosmosClientBuilder()
    .endpoint(endpoint)
    .key(key)
    .contentResponseOnWriteEnabled(false);

container.upsertItem(item)
    .map(CosmosItemResponse::getItem)  // ❌ getItem() returns null → NPE
    .block();

Correct Pattern

// Option 1: Keep content response enabled (default, safest for reactive)
CosmosClientBuilder builder = new CosmosClientBuilder()
    .endpoint(endpoint)
    .key(key)
    .contentResponseOnWriteEnabled(true);

// Option 2: If suppressing content, handle null explicitly
container.upsertItem(item)
    .flatMap(response -> {
        Object result = response.getItem();
        return result != null ? Mono.just(result) : Mono.empty();
    });

Recommended Rule Enhancement

Add a Reactor-specific warning to the existing sdk-java-content-response rule:

When using CosmosAsyncClient with reactive streams (Project Reactor), do not set contentResponseOnWriteEnabled(false). This causes CosmosItemResponse.getItem() to return null, which is illegal in Reactor streams and throws NullPointerException.

If you need to suppress response content for performance, handle the null case explicitly before mapping.

References

<agent_instructions>Analyse the issue and implement the proposed fix in the issue - do not update improvements log in testing folders. These changes arise from SCOPE testing (a separate tool). Make a draft PR. </agent_instructions>

Comments on the Issue (you are @copilot in this section)


📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.

Enhances the rule to warn that contentResponseOnWriteEnabled(false) causes
NullPointerException in Project Reactor pipelines when using CosmosAsyncClient,
since Reactor does not allow null signals (Reactive Streams Spec Rule 2.13).

Includes incorrect/correct code examples and scopes the "When NOT to enable"
section to synchronous CosmosClient only.

Co-authored-by: TheovanKraay <24420698+TheovanKraay@users.noreply.github.com>
Agent-Logs-Url: https://github.com/AzureCosmosDB/cosmosdb-agent-kit/sessions/6869109c-cd86-40d9-90ed-fd93499e38e1
Copilot AI changed the title [WIP] Fix NullPointerException in reactive streams with contentResponseOnWriteEnabled(false) Add Reactor NPE warning to sdk-java-content-response rule Mar 23, 2026
Copilot AI requested a review from TheovanKraay March 23, 2026 14:23
@TheovanKraay
Copy link
Copy Markdown
Contributor

@copilot resolve branch conflicts or rebase and start again

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 23, 2026

@copilot resolve branch conflicts or rebase and start again

Resolved the merge conflicts with main in 39e838a. The conflicts were in the Key Points section of sdk-java-content-response.md — I combined main's updated Spring Data Cosmos text ("handles both unwrapping and content response automatically") with the Reactor NPE warnings from this PR. Rebuilt AGENTS.md from scratch on top of main's version.

@TheovanKraay TheovanKraay marked this pull request as ready for review March 23, 2026 14:40
@TheovanKraay TheovanKraay merged commit ef7f46e into main Mar 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

contentResponseOnWriteEnabled(false) causes Reactor NPE in reactive streams

2 participants