Ollama 模型名寫錯,LangChain4j 卻拋
NullPointerException,棧裡連模型名都不提。真正的原因藏在 HTTP 層:/api/chat對不存在的模型返回 404,響應體為空。retrofit拿到的Response.body()是 null,OllamaClient回調直接對它調byteStream(),NPE 就這麼冒出來。看到這類 NPE 加 retrofit/OkHttp 棧,先去看服務端到底返回了什麼。
Issue & Env(案發現場與環境)
- 業務場景:本地用 Ollama 跑模型,Java 側用 LangChain4j 的
OllamaChatModel調生成。 - 觸發前提:
OllamaChatModel.builder().modelName("...")裡寫的模型名,本地壓根沒ollama pull過。 - 環境:langchain4j-ollama 1.0.0-alpha1(棧裡可見),Ollama 本地服務,retrofit 2.9.0 + OkHttp 4.12.0。
- 現象:調用當場拋 NPE,報錯信息裡沒有任何「模型不存在」的提示。
StackTrace(堆疊日誌)
報錯原文來自 issue #2365:
java.lang.NullPointerException: Cannot invoke "okhttp3.ResponseBody.byteStream()" because the return value of "retrofit2.Response.body()" is null
at dev.langchain4j.model.ollama.OllamaClient$2.onResponse(OllamaClient.java:164) ~[langchain4j-ollama-1.0.0-alpha1.jar:na]
at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:161) ~[retrofit-2.9.0.jar:na]
at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519) ~[okhttp-4.12.0.jar:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[na:na]
棧裡全是 HTTP 客戶端。Response.body() 返回 null 是核心線索。這個信號通常意味著響應不是 2xx,錯誤體被 retrofit 放進了 errorBody()。
Reproduce(復現程式碼)
寫一個本地不存在的模型名:
OllamaChatModel model = OllamaChatModel.builder()
.baseUrl("http://localhost:11434")
.modelName("qwen2.5:7b-not-pulled")
.build();
String answer = model.chat("你好");
只要本地沒 ollama pull qwen2.5:7b-not-pulled,這行就拋上面的 NPE。
Root Cause(根因分析)
NPE 只是二次傷害
Ollama 的 /api/chat 收到不存在的模型名時,返回 HTTP 404,且響應體為空,或結構不符合 LangChain4j 的預期。retrofit 遇到非 2xx,Response.body() 就是 null。LangChain4j 的 OllamaClient 回調沒做判空,直接對 body 調 byteStream(),於是拋 NPE。
為什麼難查
報錯裡既沒有模型名,也沒有 404。你看到的只是 HTTP 客戶端的 NPE。模型名寫錯和 NPE 之間,隔了一層沒被處理的錯誤響應。這是整件事最繞的地方。
關鍵點
真實原因在 HTTP 狀態碼裡。看到「NPE + retrofit/OkHttp 棧」,第一反應該是去看服務端返回了什麼狀態碼和 body。
後續版本
issue #2365 期望的修復,是把 NPE 換成清晰的 IllegalConfigurationException,對應 PR #2369。這一修復落在哪個版本區間,社區說法,截至撰寫時未核實。
The Fix(解決方案)
1. 先用命令行確認模型存在
ollama list
ollama pull qwen2.5:7b
模型名必須和 ollama list 裡的逐字一致,注意 tag,比如 :latest、:7b。
2. 程式碼裡對齊模型名,顯式寫 baseUrl
OllamaChatModel model = OllamaChatModel.builder()
.baseUrl("http://localhost:11434")
.modelName("qwen2.5:7b")
.build();
把 baseUrl 顯式寫死,避免連到別的實例。
3. 加防禦:先探測 /api/tags
調模型前先確認目標模型在列表裡。不在就直接拋自己的業務例外,別讓 NPE 冒到業務層。
4. 升級 LangChain4j
升到把該 NPE 改成 IllegalConfigurationException 的版本,報錯就能自解釋。具體版本號未核實。
小結
Ollama 相關問題先 curl http://localhost:11434/api/tags 和 ollama list,再看 Java 棧。看到 retrofit/OkHttp 裡的 NPE,一律先懷疑 HTTP 層返回了非預期響應。
