Skip to content

fix: handle null AiMessage.text() in LangChain4j.toParts()#1035

Open
anandnair2005 wants to merge 1 commit intogoogle:mainfrom
anandnair2005:fix/langchain4j-toparts-null-text
Open

fix: handle null AiMessage.text() in LangChain4j.toParts()#1035
anandnair2005 wants to merge 1 commit intogoogle:mainfrom
anandnair2005:fix/langchain4j-toparts-null-text

Conversation

@anandnair2005
Copy link

Summary

  • LangChain4j.toParts() throws NullPointerException when AiMessage.text() is null (tool-call-only LLM responses in multi-agent setups)
  • Added null guard to skip text parts when text is null, returning an empty parts list
  • Added unit test covering the null text scenario

Fixes #1034

Details

AiMessage.text() can legitimately be null when the LLM returns a tool-call-only response (e.g., during sub-agent delegation). The AutoValue-generated Part.Builder.text() rejects null, causing an NPE. This is a known LangChain4j behavior — see langchain4j#2686 and langchain4j#986.

The fix adds a null check in the else branch of toParts() — when aiMessage.text() is null, an empty list is returned instead of crashing.

Test plan

  • New unit test testGenerateContentWithNullAiMessageText — mocks AiMessage with null text and no tool requests, asserts no NPE and empty parts list
  • All 12 existing unit tests pass
  • Integration test testStreamingRunConfig (OpenAI) passes
  • Integration tests testAgentTool and testSubAgent error due to pre-existing issue: hardcoded gemini-2.0-flash model has been retired by Google (unrelated to this change)
  • 3 Anthropic integration tests skipped (no API key available)
  • Module builds cleanly: ./mvnw clean package -pl contrib/langchain4j -am
  • CI validation on Java 17 and 21

 AiMessage.text() can be null when the LLM returns a tool-call-only
 response (e.g., during sub-agent delegation). The AutoValue-generated
 Part.Builder.text() rejects null, causing an NPE.

Add a null guard to skip text parts when text is null.
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves a critical NullPointerException in the LangChain4j utility when processing AiMessage instances where the text content is null, a common occurrence in multi-agent or tool-call-only LLM interactions. The change introduces a robust null check, preventing application crashes and improving the stability of LLM response handling.

Highlights

  • NullPointerException Fix: Addressed a NullPointerException in LangChain4j.toParts() that occurred when AiMessage.text() was null, particularly in tool-call-only LLM responses.
  • Null Guard Implementation: Implemented a null guard to skip text parts when aiMessage.text() is null, ensuring an empty list of parts is returned instead of crashing.
  • Unit Test Coverage: Included a new unit test to specifically cover the scenario where AiMessage.text() is null, verifying the fix.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • contrib/langchain4j/src/main/java/com/google/adk/models/langchain4j/LangChain4j.java
    • Added a null check for aiMessage.text() within the toParts method to prevent NullPointerException.
    • Modified the toParts method to return an empty list of parts if aiMessage.text() is null.
  • contrib/langchain4j/src/test/java/com/google/adk/models/langchain4j/LangChain4jTest.java
    • Introduced a new unit test, testGenerateContentWithNullAiMessageText, to validate the correct handling of null AiMessage.text().
Activity
  • A new unit test, testGenerateContentWithNullAiMessageText, was added and successfully passes, covering the null text scenario.
  • All 12 existing unit tests for the module passed without issues.
  • The testStreamingRunConfig integration test for OpenAI passed successfully.
  • Integration tests testAgentTool and testSubAgent encountered errors due to a pre-existing issue with a retired gemini-2.0-flash model, unrelated to this change.
  • Three Anthropic integration tests were skipped due to the unavailability of an API key.
  • The module successfully builds cleanly using ./mvnw clean package -pl contrib/langchain4j -am.
  • CI validation on Java 17 and 21 is pending.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses a NullPointerException in LangChain4j.toParts() when handling an AiMessage with null text, a valid case for tool-call-only responses. The fix is straightforward, adding a null check to return an empty list. The inclusion of a dedicated unit test is a great addition to verify the fix and prevent regressions. I have one minor suggestion to improve the code's clarity.

Comment on lines +527 to 531
if (aiMessage.text() == null) {
return List.of();
}
Part part = Part.builder().text(aiMessage.text()).build();
return List.of(part);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While the logic is correct, this block can be made slightly more efficient and readable by avoiding the repeated call to aiMessage.text(). Storing the result in a local variable first makes the code cleaner and more concise.

Suggested change
if (aiMessage.text() == null) {
return List.of();
}
Part part = Part.builder().text(aiMessage.text()).build();
return List.of(part);
String text = aiMessage.text();
if (text == null) {
return List.of();
}
return List.of(Part.builder().text(text).build());

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.

LangChain4j.toParts() throws NPE when AiMessage.text() is null

1 participant