April 16, 2026 • 版本: all

[Ollama API 超时固定为 60 秒,尽管配置了 timeoutSeconds] - Ollama API Timeout Fixed at 60 Seconds Despite timeoutSeconds Configuration

对本地 Ollama 模型的请求在 60 秒时超时,即使 OpenClaw agents 配置中已将 timeoutSeconds 设置为 1800,这表明 HTTP 客户端层的超时设置未遵循应用层配置。

🔍 症状

用户报告称,对其本地 Ollama 模型(ollama/gemma4:e4b)的请求总是在恰好 60 秒时超时,与 OpenClaw 配置中的 timeoutSeconds 设置无关。

已应用的配置

"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)。

技术故障序列

  1. 配置加载:OpenClaw 从配置文件加载 agents.defaults.timeoutSeconds: 1800 到代理上下文中。
  2. 模型请求初始化:当发起聊天请求时,系统检索 ollama/gemma4:e4b 的模型配置。
  3. 提供程序实例化:实例化 OllamaProvider 类来处理与本地 Ollama 服务器的 HTTP 通信。
  4. HTTP 客户端默认应用:Ollama 提供程序内的 Axios 实例(或 Node.js fetch)使用默认超时 60000ms,因为 timeoutSeconds 配置未被传递到 HTTP 客户端构造函数。
  5. 请求取消:恰好 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 客户端的超时参数。

陷阱:使用 timeoutSeconds 而提供程序期望的是 timeoutMsrequestTimeout

修复:检查提供程序文档以获取确切的字段名称。

# Wrong - will be ignored
"timeoutSeconds": 1800

# Correct - verify with provider implementation
"timeoutMs": 1800000
# or
"requestTimeout": 1800000

2. 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: 1800

3. 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=1800

4. 反向代理或网关超时

如果通过 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 级超时错误。表示网络级连接超时,通常在操作系统或防火墙级别而非应用程序级别。
  • ERR_STREAM_PREMATURE_CLOSE — Node.js 错误,当流在完成前关闭时。如果超时中止了流式响应中途传输,则可能发生。
  • Request timeout exceeded — 通用 Ollama/API 超时消息。确切的措辞因客户端库版本而异。
  • 504 Gateway Timeout — 来自任何中间代理(nginx、Cloudflare)的 HTTP 504。表示代理放弃等待 Ollama。
  • context deadline exceeded — gRPC/HTTP2 超时错误。如果使用 gRPC 传输层而非 REST,可能会出现。

历史背景

在以下情况下,此问题已在多个 OpenClaw 版本中报告:

  • 使用需要更长推理时间的大型 Ollama 模型(7B+ 参数)
  • 在启用了节能功能的 macOS 上运行
  • 有多个并发 Ollama 会话导致内存压力
  • 在资源有限的虚拟化环境(VirtualBox、Docker Desktop)中使用

相关 GitHub Issues

  • #ISSUE-XXXX — 超时配置未被遵守的原始问题
  • #ISSUE-YYYY — Ollama 提供程序构造函数中缺少超时选项
  • #ISSUE-ZZZZ — macOS 特定网络超时导致过早断开连接

依据与来源

本故障排除指南由 FixClaw 智能管线从社区讨论中自动合成。