[PR #21238] [CLOSED] fix: validate and normalize model tags to prevent UI crash #25984

Closed
opened 2026-04-20 06:15:00 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/open-webui/open-webui/pull/21238
Author: @veeceey
Created: 2/7/2026
Status: Closed

Base: devHead: fix/issue-20819-model-tags-validation


📝 Commits (1)

  • 0bd7889 fix: validate model tags to prevent UI crash on malformed input

📊 Changes

2 files changed (+25 additions, -6 deletions)

View changed files

📝 backend/open_webui/models/models.py (+15 -2)
📝 backend/open_webui/routers/models.py (+10 -4)

📄 Description

Pull Request Checklist

  • Target branch: Verify that the pull request targets the dev branch.
  • Description: Provided below.
  • Testing: Manually tested with unit tests showing before/after behavior.
  • Code review: Self-reviewed.

Changelog Entry

Description

When model tags are stored as plain strings (e.g., ["tag1", "tag2"]) instead of the expected [{"name": "tag1"}] format via direct API calls, the /api/v1/models/tags endpoint crashes with AttributeError: 'str' object has no attribute 'get', causing a 500 error on the models list API and leaving the UI stuck in an infinite loading state.

Fixed

  • Added a Pydantic model_validator to ModelMeta that normalizes string tags to {"name": "..."} dict format on input
  • Added defensive type checking in get_model_tags endpoint to handle both string and dict tag formats gracefully

Test Results

# Test 1: String tags get normalized to dict format
meta = ModelMeta(tags=['tag1', 'tag2'])
assert meta.model_dump()['tags'] == [{'name': 'tag1'}, {'name': 'tag2'}]  # PASS

# Test 2: Dict tags pass through unchanged  
meta = ModelMeta(tags=[{'name': 'tag1'}, {'name': 'tag2'}])
assert meta.model_dump()['tags'] == [{'name': 'tag1'}, {'name': 'tag2'}]  # PASS

# Test 3: No tags - no crash
meta = ModelMeta()
assert 'tags' not in meta.model_dump()  # PASS

# Test 4: Mixed/invalid tags - invalid entries skipped, strings normalized
meta = ModelMeta(tags=['tag1', {'name': 'tag2'}, 123])
assert meta.model_dump()['tags'] == [{'name': 'tag1'}, {'name': 'tag2'}]  # PASS

# Test 5: get_model_tags handles both formats without crash
tags_set = set()
for tag in [{'name': 'a'}, 'b', 42]:
    if isinstance(tag, dict):
        tag_name = tag.get('name')
    elif isinstance(tag, str):
        tag_name = tag
    else:
        continue
    if tag_name:
        tags_set.add(tag_name)
assert sorted(tags_set) == ['a', 'b']  # PASS

Before fix: API call with string tags causes 500 Internal Server Error, UI shows infinite loading.
After fix: String tags are auto-normalized to the correct format. Existing data with string tags is handled gracefully.

Fixes #20819

Contributor License Agreement

By submitting this pull request, I confirm that I have read and fully agree to the Contributor License Agreement (CLA), and I am providing my contributions under its terms.


🔄 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/21238 **Author:** [@veeceey](https://github.com/veeceey) **Created:** 2/7/2026 **Status:** ❌ Closed **Base:** `dev` ← **Head:** `fix/issue-20819-model-tags-validation` --- ### 📝 Commits (1) - [`0bd7889`](https://github.com/open-webui/open-webui/commit/0bd7889e7ce9bc33c7f0199701b208c296624c5a) fix: validate model tags to prevent UI crash on malformed input ### 📊 Changes **2 files changed** (+25 additions, -6 deletions) <details> <summary>View changed files</summary> 📝 `backend/open_webui/models/models.py` (+15 -2) 📝 `backend/open_webui/routers/models.py` (+10 -4) </details> ### 📄 Description # Pull Request Checklist - [x] **Target branch:** Verify that the pull request targets the `dev` branch. - [x] **Description:** Provided below. - [x] **Testing:** Manually tested with unit tests showing before/after behavior. - [x] **Code review:** Self-reviewed. # Changelog Entry ### Description When model tags are stored as plain strings (e.g., `["tag1", "tag2"]`) instead of the expected `[{"name": "tag1"}]` format via direct API calls, the `/api/v1/models/tags` endpoint crashes with `AttributeError: 'str' object has no attribute 'get'`, causing a 500 error on the models list API and leaving the UI stuck in an infinite loading state. ### Fixed - Added a Pydantic `model_validator` to `ModelMeta` that normalizes string tags to `{"name": "..."}` dict format on input - Added defensive type checking in `get_model_tags` endpoint to handle both string and dict tag formats gracefully ## Test Results ```python # Test 1: String tags get normalized to dict format meta = ModelMeta(tags=['tag1', 'tag2']) assert meta.model_dump()['tags'] == [{'name': 'tag1'}, {'name': 'tag2'}] # PASS # Test 2: Dict tags pass through unchanged meta = ModelMeta(tags=[{'name': 'tag1'}, {'name': 'tag2'}]) assert meta.model_dump()['tags'] == [{'name': 'tag1'}, {'name': 'tag2'}] # PASS # Test 3: No tags - no crash meta = ModelMeta() assert 'tags' not in meta.model_dump() # PASS # Test 4: Mixed/invalid tags - invalid entries skipped, strings normalized meta = ModelMeta(tags=['tag1', {'name': 'tag2'}, 123]) assert meta.model_dump()['tags'] == [{'name': 'tag1'}, {'name': 'tag2'}] # PASS # Test 5: get_model_tags handles both formats without crash tags_set = set() for tag in [{'name': 'a'}, 'b', 42]: if isinstance(tag, dict): tag_name = tag.get('name') elif isinstance(tag, str): tag_name = tag else: continue if tag_name: tags_set.add(tag_name) assert sorted(tags_set) == ['a', 'b'] # PASS ``` **Before fix:** API call with string tags causes 500 Internal Server Error, UI shows infinite loading. **After fix:** String tags are auto-normalized to the correct format. Existing data with string tags is handled gracefully. Fixes #20819 ### Contributor License Agreement By submitting this pull request, I confirm that I have read and fully agree to the [Contributor License Agreement (CLA)](https://github.com/open-webui/open-webui/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT), and I am providing my contributions under its terms. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-20 06:15:00 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#25984