Fix title, tag, follow-up, and other task generation endpoints returning 404 or crashing with TypeError: 'NoneType' object is not callable when users chat via direct connections with a server-side task model configured.
Changelog Entry
Fixed
Task generation (title, tags, follow-ups, emoji, etc.) now works correctly when users chat via direct connections with a configured server-side task model
Problem
When ENABLE_DIRECT_CONNECTIONS=true and users chat with models from their own API keys, all background task generation (auto-title, tags, follow-ups, emoji, etc.) fails:
HTTP endpoint path (tasks.py): The model existence check validates the chat model against request.app.state.MODELS before get_task_model_id() can resolve to the configured task model. Direct connection models aren't in the server's MODELS registry, so this raises a 404 — even though the configured task model is available.
Internal middleware path (middleware.py): After a chat completion, background_tasks_handler calls generate_title/generate_chat_tags with the original request that still has request.state.direct = True. This routes task generation through generate_direct_chat_completion, which calls get_event_call() — but the WebSocket session isn't available in the background task context, so event_caller is None and await event_caller({...}) crashes with:
middleware.py:5020 → await background_tasks_handler(ctx)
middleware.py:3112 → res = await generate_title(request, {...}, user)
tasks.py:220 → return await generate_direct_chat_completion(...)
chat.py:140 → res = await event_caller({...})
TypeError: 'NoneType' object is not callable
Changes
backend/open_webui/routers/tasks.py
Task endpoints now always use request.app.state.MODELS (server-side models) instead of conditionally using the narrow direct-connection models dict
Model validation moved afterget_task_model_id() and validates the resolved task_model_id instead of the chat model_id, allowing the task model override to work for direct connection users
backend/open_webui/utils/middleware.py
background_tasks_handler temporarily clears request.state.direct and request.state.model before running task generation, so generate_chat_completion routes through the standard server-side path
Original state is restored after task generation completes
Testing
Tested on a production AWS Fargate deployment (3 ECS tasks, Aurora PostgreSQL, ALB) with:
ENABLE_DIRECT_CONNECTIONS=true
ENABLE_OLLAMA_API=False
Server-level OpenAI connection via LiteLLM gateway (28 models)
Task Model set to "Amazon Nova Micro" in Admin Settings
Users chatting via direct connections to various models (Claude, GPT, Gemini, etc.)
Before fix: Every new chat via direct connection produced TypeError in logs, title fell back to user's first message, tags not generated.
After fix: Title and tags auto-generate correctly using the configured task model. Zero errors in logs. Verified via CloudWatch log monitoring.
Test plan
Start a new chat with a direct connection model → title and tags auto-generate using the configured task model
Start a new chat with a server-level model → title and tags auto-generate (no regression)
Verify no TypeError or 404 errors in server logs after chat completions
Manually trigger title regeneration via the UI → works for both direct and server-level models
Verify task model config (/api/v1/tasks/config) is respected — tasks use the configured task model, not the chat model
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.
## 📋 Pull Request Information
**Original PR:** https://github.com/open-webui/open-webui/pull/24099
**Author:** [@champumbc](https://github.com/champumbc)
**Created:** 4/24/2026
**Status:** ❌ Closed
**Base:** `dev` ← **Head:** `fix/direct-connection-task-generation`
---
### 📝 Commits (10+)
- [`fe6783c`](https://github.com/open-webui/open-webui/commit/fe6783c16699911c7be17392596d579333fb110c) Merge pull request #19030 from open-webui/dev
- [`fc05e0a`](https://github.com/open-webui/open-webui/commit/fc05e0a6c5d39da60b603b4d520f800d6e36f748) Merge pull request #19405 from open-webui/dev
- [`e3faec6`](https://github.com/open-webui/open-webui/commit/e3faec62c58e3a83d89aa3df539feacefa125e0c) Merge pull request #19416 from open-webui/dev
- [`9899293`](https://github.com/open-webui/open-webui/commit/9899293f050ad50ae12024cbebee7e018acd851e) Merge pull request #19448 from open-webui/dev
- [`140605e`](https://github.com/open-webui/open-webui/commit/140605e660b8186a7d5c79fb3be6ffb147a2f498) Merge pull request #19462 from open-webui/dev
- [`6f1486f`](https://github.com/open-webui/open-webui/commit/6f1486ffd0cb288d0e21f41845361924e0d742b3) Merge pull request #19466 from open-webui/dev
- [`d95f533`](https://github.com/open-webui/open-webui/commit/d95f533214e3fe5beb5e41ec1f349940bc4c7043) Merge pull request #19729 from open-webui/dev
- [`a727153`](https://github.com/open-webui/open-webui/commit/a7271532f8a38da46785afcaa7e65f9a45e7d753) 0.6.43 (#20093)
- [`6adde20`](https://github.com/open-webui/open-webui/commit/6adde203cd292a9e3af9c64a2ae36b603fed096a) Merge pull request #20394 from open-webui/dev
- [`f9b0534`](https://github.com/open-webui/open-webui/commit/f9b0534e0c442631d1cb7205169588b9b6204179) Merge pull request #20522 from open-webui/dev
### 📊 Changes
**2 files changed** (+94 additions, -97 deletions)
<details>
<summary>View changed files</summary>
📝 `backend/open_webui/routers/tasks.py` (+78 -97)
📝 `backend/open_webui/utils/middleware.py` (+16 -0)
</details>
### 📄 Description
## Pull Request Checklist
- [x] PR targets the `dev` branch
- [x] Clear description of changes included
- [x] Changes follow existing code style and conventions
- [x] Self-reviewed the code changes
- [x] Manually tested changes and verified they work as expected
## Contributor License Agreement (CLA)
- [x] By submitting this pull request, I confirm that I have read and fully agree to the [Contributor License Agreement (CLA)](https://docs.openwebui.com/cla).
## Summary
Fix title, tag, follow-up, and other task generation endpoints returning 404 or crashing with `TypeError: 'NoneType' object is not callable` when users chat via direct connections with a server-side task model configured.
### Changelog Entry
#### Fixed
- Task generation (title, tags, follow-ups, emoji, etc.) now works correctly when users chat via direct connections with a configured server-side task model
## Problem
When `ENABLE_DIRECT_CONNECTIONS=true` and users chat with models from their own API keys, all background task generation (auto-title, tags, follow-ups, emoji, etc.) fails:
1. **HTTP endpoint path (tasks.py):** The model existence check validates the *chat* model against `request.app.state.MODELS` before `get_task_model_id()` can resolve to the configured task model. Direct connection models aren't in the server's MODELS registry, so this raises a 404 — even though the configured task model is available.
2. **Internal middleware path (middleware.py):** After a chat completion, `background_tasks_handler` calls `generate_title`/`generate_chat_tags` with the original request that still has `request.state.direct = True`. This routes task generation through `generate_direct_chat_completion`, which calls `get_event_call()` — but the WebSocket session isn't available in the background task context, so `event_caller` is `None` and `await event_caller({...})` crashes with:
```
middleware.py:5020 → await background_tasks_handler(ctx)
middleware.py:3112 → res = await generate_title(request, {...}, user)
tasks.py:220 → return await generate_direct_chat_completion(...)
chat.py:140 → res = await event_caller({...})
TypeError: 'NoneType' object is not callable
```
## Changes
### `backend/open_webui/routers/tasks.py`
- Task endpoints now always use `request.app.state.MODELS` (server-side models) instead of conditionally using the narrow direct-connection models dict
- Model validation moved **after** `get_task_model_id()` and validates the resolved `task_model_id` instead of the chat `model_id`, allowing the task model override to work for direct connection users
### `backend/open_webui/utils/middleware.py`
- `background_tasks_handler` temporarily clears `request.state.direct` and `request.state.model` before running task generation, so `generate_chat_completion` routes through the standard server-side path
- Original state is restored after task generation completes
## Testing
Tested on a production AWS Fargate deployment (3 ECS tasks, Aurora PostgreSQL, ALB) with:
- `ENABLE_DIRECT_CONNECTIONS=true`
- `ENABLE_OLLAMA_API=False`
- Server-level OpenAI connection via LiteLLM gateway (28 models)
- Task Model set to "Amazon Nova Micro" in Admin Settings
- Users chatting via direct connections to various models (Claude, GPT, Gemini, etc.)
**Before fix:** Every new chat via direct connection produced `TypeError` in logs, title fell back to user's first message, tags not generated.
**After fix:** Title and tags auto-generate correctly using the configured task model. Zero errors in logs. Verified via CloudWatch log monitoring.
## Test plan
- [x] Start a new chat with a direct connection model → title and tags auto-generate using the configured task model
- [x] Start a new chat with a server-level model → title and tags auto-generate (no regression)
- [x] Verify no `TypeError` or 404 errors in server logs after chat completions
- [x] Manually trigger title regeneration via the UI → works for both direct and server-level models
- [x] Verify task model config (`/api/v1/tasks/config`) is respected — tasks use the configured task model, not the chat model
## Related Issues
Fixes #24092
Fixes #24095
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---
<sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
📋 Pull Request Information
Original PR: https://github.com/open-webui/open-webui/pull/24099
Author: @champumbc
Created: 4/24/2026
Status: ❌ Closed
Base:
dev← Head:fix/direct-connection-task-generation📝 Commits (10+)
fe6783cMerge pull request #19030 from open-webui/devfc05e0aMerge pull request #19405 from open-webui/deve3faec6Merge pull request #19416 from open-webui/dev9899293Merge pull request #19448 from open-webui/dev140605eMerge pull request #19462 from open-webui/dev6f1486fMerge pull request #19466 from open-webui/devd95f533Merge pull request #19729 from open-webui/deva7271530.6.43 (#20093)6adde20Merge pull request #20394 from open-webui/devf9b0534Merge pull request #20522 from open-webui/dev📊 Changes
2 files changed (+94 additions, -97 deletions)
View changed files
📝
backend/open_webui/routers/tasks.py(+78 -97)📝
backend/open_webui/utils/middleware.py(+16 -0)📄 Description
Pull Request Checklist
devbranchContributor License Agreement (CLA)
Summary
Fix title, tag, follow-up, and other task generation endpoints returning 404 or crashing with
TypeError: 'NoneType' object is not callablewhen users chat via direct connections with a server-side task model configured.Changelog Entry
Fixed
Problem
When
ENABLE_DIRECT_CONNECTIONS=trueand users chat with models from their own API keys, all background task generation (auto-title, tags, follow-ups, emoji, etc.) fails:HTTP endpoint path (tasks.py): The model existence check validates the chat model against
request.app.state.MODELSbeforeget_task_model_id()can resolve to the configured task model. Direct connection models aren't in the server's MODELS registry, so this raises a 404 — even though the configured task model is available.Internal middleware path (middleware.py): After a chat completion,
background_tasks_handlercallsgenerate_title/generate_chat_tagswith the original request that still hasrequest.state.direct = True. This routes task generation throughgenerate_direct_chat_completion, which callsget_event_call()— but the WebSocket session isn't available in the background task context, soevent_callerisNoneandawait event_caller({...})crashes with:Changes
backend/open_webui/routers/tasks.pyrequest.app.state.MODELS(server-side models) instead of conditionally using the narrow direct-connection models dictget_task_model_id()and validates the resolvedtask_model_idinstead of the chatmodel_id, allowing the task model override to work for direct connection usersbackend/open_webui/utils/middleware.pybackground_tasks_handlertemporarily clearsrequest.state.directandrequest.state.modelbefore running task generation, sogenerate_chat_completionroutes through the standard server-side pathTesting
Tested on a production AWS Fargate deployment (3 ECS tasks, Aurora PostgreSQL, ALB) with:
ENABLE_DIRECT_CONNECTIONS=trueENABLE_OLLAMA_API=FalseBefore fix: Every new chat via direct connection produced
TypeErrorin logs, title fell back to user's first message, tags not generated.After fix: Title and tags auto-generate correctly using the configured task model. Zero errors in logs. Verified via CloudWatch log monitoring.
Test plan
TypeErroror 404 errors in server logs after chat completions/api/v1/tasks/config) is respected — tasks use the configured task model, not the chat modelRelated Issues
Fixes #24092
Fixes #24095
🤖 Generated with Claude Code
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.