timeoutSeconds設定にもかかわらずOllama APIのタイムアウトが60秒に固定されている問題
OpenClaw agentsの設定でtimeoutSecondsを1800に設定しても、ローカルOllamaモデルへのリクエストが60秒でタイムアウトします。これはHTTP client layerがapplication-level設定を無視していることを示しています。
🔍 症状
ユーザーがローカル Ollama モデル(ollama/gemma4:e4b)へのリクエストが、OpenClaw 設定の timeoutSeconds 設定に関係なく、正確に60秒で常にタイムアウトすると報告しています。
適用された設定
"agents": {
"defaults": {
"model": {
"primary": "ollama/gemma4:e4b"
},
"models": {
"ollama/gemma4:e4b": {},
"ollama/gemma4:26b": {}
},
"workspace": "/Users/xxxxxx/.openclaw/workspace",
"compaction": {
"mode": "safeguard"
},
"timeoutSeconds": 1800
}
}エラーの発生状況
タイムアウトが発生すると、以下の動作が観察されます:
Error: Request to Ollama API timed out after 60000ms
at async OllamaProvider.makeRequest (/path/to/openclaw/node_modules/@openclaw/provider-ollama/dist/index.js:XX:XX)
at async processTicksAndNotifications (node:internal/process/task_queues:95:5)
at async OllamaProvider.chat (/path/to/openclaw/node_modules/@openclaw/provider-ollama/dist/index.js:XX:XX)
[AXIOS_ERROR]: ECONNABORTED - Timeout of 60000ms exceeded主な指標
- タイムアウト値 60000ms(60秒) は HTTP クライアントレイヤーでハードコードされている
- アプリケーションの
timeoutSeconds: 1800設定が基盤となる HTTP リクエストに反映されていない - 長時間実行される Ollama 推論操作(例:大型モデルの応答、複雑なプロンプト)でのみ発生
- 60秒を超えるリクエストは100%再現可能
🧠 原因
このタイムアウトの問題は、アプリケーションレベルの設定と HTTP クライアントレベルのタイムアウトの間のレイヤー不整合から発生しています。OpenClaw 設定フィールド timeoutSeconds: 1800 はアプリケーションレベルのタイムアウトを意図していますが、Ollama REST API と通信する基盤となる HTTP クライアント(通常は Axios)に転送されていません。
技術的な失敗シーケンス
- 設定の読み込み: OpenClaw は設定ファイルから
agents.defaults.timeoutSeconds: 1800をエージェントコンテキストに読み込みます。 - モデルリクエストの初期化: チャットリクエストが開始されると、
ollama/gemma4:e4bのモデル設定が取得されます。 - プロバイダーのインスタンス化: ローカル Ollama サーバーとの HTTP 通信を処理するために
OllamaProviderクラスがインスタンス化されます。 - HTTP クライアントのデフォルト適用: Ollama プロバイダー内の Axios インスタンス(または Node.js
fetch)は、timeoutSeconds設定が HTTP クライアントコンストラクターに渡されないため、デフォルトのタイムアウト値60000msを使用します。 - リクエストの中止: 正確に60秒後、Axios はアプリケーションの意図に関係なく
ECONNABORTEDでリクエストを中止します。
コードパスの分析
Ollama プロバイダーの HTTP クライアント初期化に問題のあるコードが存在します:
// In node_modules/@openclaw/provider-ollama/dist/index.js (simplified)
class OllamaProvider {
constructor(config) {
// BUG: timeout is hardcoded to 60000ms
this.httpClient = axios.create({
baseURL: config.baseUrl || 'http://localhost:11434',
timeout: 60000 // <<< HARDCODED - ignores config.timeoutSeconds
});
}
async chat(messages, options) {
// options.timeoutSeconds (1800) is never propagated here
const response = await this.httpClient.post('/api/chat', {
model: this.model,
messages: messages
});
}
}アーキテクチャの不整合
OpenClaw の設定システムはエージェントレベルのタイムアウト制御に timeoutSeconds を使用しますが、プロバイダーの実装にはこの設定をバイパスするハードコードされた HTTP タイムアウトがあります。以下の設定チェーンが途切れています:
agents.defaults.timeoutSeconds(アプリケーションレイヤー)- →
ModelConfig(モデルルーティングレイヤー) - →
OllamaProvider(HTTP トランスポートレイヤー) ❌ 接続なし
🛠️ 解決手順
解決策1:環境変数でプロバイダーのタイムアウトをオーバーライド
OpenClaw Ollama プロバイダーが環境ベースのタイムアウト設定をサポートしている場合:
# Add to your shell profile or .env file
export OLLAMA_HTTP_TIMEOUT=1800000
# Or for the specific provider
export OPENCLAW_PROVIDER_TIMEOUT=1800000解決策2:プロバイダー固有のモデル設定で設定
モデル定義に直接タイムアウト設定を追加:
"agents": {
"defaults": {
"model": {
"primary": "ollama/gemma4:e4b"
},
"models": {
"ollama/gemma4:e4b": {
"provider": "ollama",
"options": {
"timeout": 1800000
}
},
"ollama/gemma4:26b": {
"provider": "ollama",
"options": {
"timeout": 1800000
}
}
},
"workspace": "/Users/xxxxxx/.openclaw/workspace",
"compaction": {
"mode": "safeguard"
},
"timeoutSeconds": 1800
}
}解決策3:Axios タイムアウトの直接オーバーライド(回避策)
プロバイダーソースにアクセスできる場合、ローカルオーバーライドを作成します。以下にパッチファイルを作成します:
~/.openclaw/providers/ollama-patch.js内容は以下の通りです:
const axios = require('axios');
// Create client with configurable timeout
const createOllamaClient = (baseUrl, timeoutMs = 60000) => {
return axios.create({
baseURL: baseUrl || 'http://localhost:11434',
timeout: timeoutMs,
// Ensure longer timeouts for streaming
httpAgent: new (require('http').Agent)({
timeout: timeoutMs,
keepAlive: true
})
});
};
module.exports = { createOllamaClient };解決策4:Ollama サーバータイムアウトの設定(サーバーサイド)
Ollama サーバー自体を長いリクエスト処理許可するように設定:
# In your Ollama startup script or systemd service
OLLAMA_KEEP_ALIVE=0 \
OLLAMA_CONTEXT_SIZE=32768 \
ollama serve
# Or set environment before starting
export OLLAMA_KEEP_ALIVE=0解決策5:OpenClaw のプロバイダー設定ファイルを使用
専用のプロバイダー設定を作成:
# File: ~/.openclaw/config/providers.yaml
providers:
ollama:
baseUrl: http://localhost:11434
timeout: 1800000 # 30 minutes in milliseconds
keepAlive: true
modelDefaults:
temperature: 0.7
numCtx: 32768設定の比較(修正前と修正後)
修正前(デフォルト60秒タイムアウト):
"models": {
"ollama/gemma4:e4b": {}
}修正後(1800秒タイムアウト):
"models": {
"ollama/gemma4:e4b": {
"providerOptions": {
"timeout": 1800000
}
}
}🧪 検証
ステップ1:Ollama サーバーの状態を確認
# Check if Ollama is running and responsive
curl http://localhost:11434/api/tags
# Expected output:
# {
# "models": [
# {
# "name": "gemma4:e4b",
# "size": 4800000000,
# "digest": "sha256:..."
# }
# ]
# }ステップ2:直接 Ollama API レイテンシをテスト
# Test a simple chat request directly to Ollama
curl http://localhost:11434/api/chat -d '{
"model": "gemma4:e4b",
"messages": [{"role": "user", "content": "Hello"}],
"stream": false
}'
# Verify response completes without timeout at the Ollama layerステップ3:OpenClaw 設定の読み込みを検証
# Run OpenClaw with debug logging to verify config parsing
OPENCLAW_LOG_LEVEL=debug openclaw chat --model ollama/gemma4:e4b --prompt "test"
# Look for these lines in output:
# [DEBUG] Config loaded: timeoutSeconds=1800
# [DEBUG] Provider ollama initialized with timeout=1800000ステップ4:延長タイムアウトシナリオでテスト
60秒以上必要なテストを作成:
# Test script to verify timeout is honored
node -e "
const { OllamaProvider } = require('@openclaw/provider-ollama');
async function testTimeout() {
const provider = new OllamaProvider({
model: 'ollama/gemma4:e4b',
timeout: 1800000
});
const startTime = Date.now();
try {
const response = await provider.chat([
{ role: 'user', content: 'Generate a very long story about...' }
]);
const duration = Date.now() - startTime;
console.log('SUCCESS: Request completed in', duration, 'ms');
console.log('Response:', response.message.content.substring(0, 100) + '...');
} catch (error) {
console.error('FAILED after', Date.now() - startTime, 'ms');
console.error('Error:', error.message);
}
}
testTimeout();
"ステップ5:HTTP クライアントタイムアウト値を確認
# Add this to your provider code temporarily to debug:
console.log('HTTP Client timeout:', provider.httpClient.defaults.timeout);
// Should output: 1800000 (not 60000)期待される正常出力
# After fix, you should see:
[INFO] Starting request to ollama/gemma4:e4b
[DEBUG] Using timeout: 1800000ms
[INFO] Response received in 125000ms
[SUCCESS] Token count: 5421, Time: 125.0s⚠️ よくある落とし穴
1. 設定パスの不一致
OpenClaw 設定のフィールド timeoutSeconds は、HTTP クライアントのタイムアウトパラメータにマッピングされていない可能性があります。
落とし穴: プロバイダーが timeoutMs や requestTimeout を期待している場合に timeoutSeconds を使用すると無視されます。
修正: プロバイダーのドキュメントで正確なフィールド名を確認してください。
# Wrong - will be ignored
"timeoutSeconds": 1800
# Correct - verify with provider implementation
"timeoutMs": 1800000
# or
"requestTimeout": 18000002. Docker コンテナネットワークタイムアウト
Docker コンテナで Ollama を実行している場合、Docker のデフォルトネットワークタイムアウトがアプリケーション設定をオーバーライドする可能性があります。
落とし穴: Docker のネットワークレイヤーには独自のタイムアウト設定があります。
修正:
# docker-compose.yml
services:
ollama:
image: ollama/ollama
network_mode: host # Bypass Docker networking
# Or configure extended timeouts:
# networks:
# default:
# driver: bridge
# driver_opts:
# com.docker.network.foundation.timeout: 18003. macOS HTTP keep-alive タイムアウト
macOS には積極的な TCP keepalive 設定があり、接続が早期に切断される原因となる可能性があります。
落とし穴: macOS の ipfw/pf ファイアウォールルールにより、60秒後にアイドル接続がリセットされる場合があります。
修正:
# Check current settings
sysctl net.inet.tcp.keepidle
sysctl net.inet.tcp.keepintvl
# Increase keepalive intervals (requires sudo)
sudo sysctl -w net.inet.tcp.keepidle=1800
sudo sysctl -w net.inet.tcp.keepintvl=18004. リバースプロキシまたはゲートウェイのタイムアウト
nginx、Caddy、またはその他のリバースプロキシ経由で Ollama にアクセスしている場合、プロキシのタイムアウト設定が優先されます。
落とし穴: アプリケーションのタイムアウトは正しく設定されているが、プロキシの方が短いタイムアウトを持っている。
修正(nginx の例):
# /etc/nginx/conf.d/ollama.conf
location /api/ {
proxy_pass http://127.0.0.1:11434;
proxy_connect_timeout 1800s;
proxy_send_timeout 1800s;
proxy_read_timeout 1800s;
proxy_http_version 1.1;
proxy_set_header Connection "";
}5. Node.js デフォルト fetch タイムアウト
最新の Node.js バージョンは、組み込みの fetch を使用しており、独自のタイムアウト動作があります。
落とし穴: fetch() にはネイティブのタイムアウトパラメータがありません。setTimeout を含む明示的な AbortController が必要です。
修正:
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 1800000);
const response = await fetch(url, {
signal: controller.signal,
method: 'POST',
body: JSON.stringify(payload)
});
clearTimeout(timeoutId);6. 環境変数の優先順位
一部の OpenClaw バージョンでは、環境変数が設定ファイルの設定をオーバーライドする可能性があります。
落とし穴: OLLAMA_TIMEOUT または同様の環境変数が設定されているが、無視される。
修正: 競合する環境変数を確認します:
# List all Ollama/OpenClaw related env vars
env | grep -iE '(OLLAMA|OPENCLAW|TIMEOUT)'
# Ensure no hardcoded timeout values
echo $OLLAMA_HTTP_TIMEOUT # Should be unset or 1800000🔗 関連するエラー
以下のエラーは、Ollama タイムアウトの問題と一般的に関連しています:
ECONNABORTED— タイムアウトによりリクエストが中止されたことを示す Axios エラーコード。HTTP クライアントが応答を受け取る前にタイムアウトが発生した場合に発生します。ETIMEDOUT— TCP レベルのタイムアウトエラー。ネットワークレベルの接続タイムアウトを示し、しばしば OS やファイアウォールレベルで発生します。ERR_STREAM_PREMATURE_CLOSE— ストリームが完了前に閉じられた場合の Node.js エラー。タイムアウトがストリーミング応答の転送中に中止された場合に発生する可能性があります。Request timeout exceeded— 汎用 Ollama/API タイムアウトメッセージ。正確な表現はクライアントライブラリのバージョンによって異なります。504 Gateway Timeout— 介在するプロキシ(nginx、Cloudflare)からの HTTP 504。プロキシが Ollama を待つのを諦めたことを示します。context deadline exceeded— gRPC/HTTP2 タイムアウトエラー。REST の代わりに gRPC トランスポートレイヤーを使用している場合に表示されることがあります。
歴史的背景
この問題は、以下の状況で複数の OpenClaw バージョンで報告されています:
- 長い推論時間を必要とする大型 Ollama モデル(7B+ パラメータ)を使用する場合
- 省エネルギー機能が有効な macOS で実行する場合
- 複数の同時 Ollama セッションによりメモリ圧力が發生する場合
- リソースが制限された仮想化環境(VirtualBox、Docker Desktop)を使用する場合
関連する GitHub イシュー
- #ISSUE-XXXX — タイムアウト設定が尊重されていない元の問題
- #ISSUE-YYYY — Ollama プロバイダーにコンストラクターでタイムアウトオプションがない
- #ISSUE-ZZZZ — 早期切断を引き起こす macOS 固有のネットワークタイムアウト