From 343a12353fbe26245072d3eec45759ddd0d42336 Mon Sep 17 00:00:00 2001 From: U8F69 Date: Wed, 28 Jan 2026 20:06:31 +0800 Subject: [PATCH 1/6] fix(chat): improve error handling for chat API failures --- CHANGELOG_EXTRA.md | 6 + package-lock.json | 4 +- package.json | 2 +- src/lib/components/chat/Chat.svelte | 163 +++++++++++++++------------- 4 files changed, 95 insertions(+), 80 deletions(-) diff --git a/CHANGELOG_EXTRA.md b/CHANGELOG_EXTRA.md index 9d0d8289f0..be857c3f76 100644 --- a/CHANGELOG_EXTRA.md +++ b/CHANGELOG_EXTRA.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.2.2] - 2026.01.28 + +### Changed + +- 优化对话接口调用失败的提示 + ## [0.7.2.1] - 2026.01.11 ### Changed diff --git a/package-lock.json b/package-lock.json index 1d4fb24caa..089ecf4e59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "open-webui", - "version": "0.7.2.1", + "version": "0.7.2.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "open-webui", - "version": "0.7.2.1", + "version": "0.7.2.2", "dependencies": { "@azure/msal-browser": "^4.5.0", "@codemirror/lang-javascript": "^6.2.2", diff --git a/package.json b/package.json index de70d1ccbd..b3d6b5b558 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "open-webui", - "version": "0.7.2.1", + "version": "0.7.2.2", "private": true, "scripts": { "dev": "npm run pyodide:fetch && vite dev --host", diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index ff41dfe472..f80513c799 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -1945,93 +1945,102 @@ } } - const res = await generateOpenAIChatCompletion( - localStorage.token, - { - stream: stream, - model: model.id, - messages: messages, - params: { - ...$settings?.params, - ...params, - stop: - (params?.stop ?? $settings?.params?.stop ?? undefined) - ? (params?.stop.split(',').map((token) => token.trim()) ?? $settings.params.stop).map( - (str) => decodeURIComponent(JSON.parse('"' + str.replace(/\"/g, '\\"') + '"')) - ) - : undefined - }, - - files: (files?.length ?? 0) > 0 ? files : undefined, - - filter_ids: selectedFilterIds.length > 0 ? selectedFilterIds : undefined, - tool_ids: toolIds.length > 0 ? toolIds : undefined, - tool_servers: ($toolServers ?? []).filter( - (server, idx) => toolServerIds.includes(idx) || toolServerIds.includes(server?.id) - ), - features: getFeatures(), - variables: { - ...getPromptVariables($user?.name, $settings?.userLocation ? userLocation : undefined) - }, - model_item: $models.find((m) => m.id === model.id), + let res; + try { + res = await generateOpenAIChatCompletion( + localStorage.token, + { + stream: stream, + model: model.id, + messages: messages, + params: { + ...$settings?.params, + ...params, + stop: + (params?.stop ?? $settings?.params?.stop ?? undefined) + ? ( + params?.stop.split(',').map((token) => token.trim()) ?? $settings.params.stop + ).map((str) => + decodeURIComponent(JSON.parse('"' + str.replace(/\"/g, '\\"') + '"')) + ) + : undefined + }, + + files: (files?.length ?? 0) > 0 ? files : undefined, + + filter_ids: selectedFilterIds.length > 0 ? selectedFilterIds : undefined, + tool_ids: toolIds.length > 0 ? toolIds : undefined, + tool_servers: ($toolServers ?? []).filter( + (server, idx) => toolServerIds.includes(idx) || toolServerIds.includes(server?.id) + ), + features: getFeatures(), + variables: { + ...getPromptVariables($user?.name, $settings?.userLocation ? userLocation : undefined) + }, + model_item: $models.find((m) => m.id === model.id), + + session_id: $socket?.id, + chat_id: $chatId, - session_id: $socket?.id, - chat_id: $chatId, + id: responseMessageId, + parent_id: userMessage?.id ?? null, + parent_message: userMessage, + + background_tasks: { + ...(!$temporaryChatEnabled && + (messages.length == 1 || + (messages.length == 2 && + messages.at(0)?.role === 'system' && + messages.at(1)?.role === 'user')) && + (selectedModels[0] === model.id || atSelectedModel !== undefined) + ? { + title_generation: $settings?.title?.auto ?? true, + tags_generation: $settings?.autoTags ?? true + } + : {}), + follow_up_generation: $settings?.autoFollowUps ?? true + }, - id: responseMessageId, - parent_id: userMessage?.id ?? null, - parent_message: userMessage, - - background_tasks: { - ...(!$temporaryChatEnabled && - (messages.length == 1 || - (messages.length == 2 && - messages.at(0)?.role === 'system' && - messages.at(1)?.role === 'user')) && - (selectedModels[0] === model.id || atSelectedModel !== undefined) + ...(stream && (model.info?.meta?.capabilities?.usage ?? false) ? { - title_generation: $settings?.title?.auto ?? true, - tags_generation: $settings?.autoTags ?? true + stream_options: { + include_usage: true + } } - : {}), - follow_up_generation: $settings?.autoFollowUps ?? true + : {}) }, + `${WEBUI_BASE_URL}/api` + ).catch(async (error) => { + console.log(error); + + let errorMessage = error; + if (error?.error?.message) { + errorMessage = error.error.message; + } else if (error?.message) { + errorMessage = error.message; + } - ...(stream && (model.info?.meta?.capabilities?.usage ?? false) - ? { - stream_options: { - include_usage: true - } - } - : {}) - }, - `${WEBUI_BASE_URL}/api` - ).catch(async (error) => { - console.log(error); - - let errorMessage = error; - if (error?.error?.message) { - errorMessage = error.error.message; - } else if (error?.message) { - errorMessage = error.message; - } - - if (typeof errorMessage === 'object') { - errorMessage = $i18n.t(`Uh-oh! There was an issue with the response.`); - } + if (typeof errorMessage === 'object') { + errorMessage = $i18n.t(`Uh-oh! There was an issue with the response.`); + } - toast.error(`${errorMessage}`); - responseMessage.error = { - content: error - }; + toast.error(`${errorMessage}`); + responseMessage.error = { + content: error + }; - responseMessage.done = true; + responseMessage.done = true; - history.messages[responseMessageId] = responseMessage; - history.currentId = responseMessageId; + history.messages[responseMessageId] = responseMessage; + history.currentId = responseMessageId; - return null; - }); + return null; + }); + } catch (e) { + console.error(e); + await handleOpenAIError(e, responseMessage); + return; + } if (res) { if (res.error) { From e5188c6b81f73764f9cad02c356bb3cabaa53eb9 Mon Sep 17 00:00:00 2001 From: U8F69 Date: Wed, 28 Jan 2026 20:06:56 +0800 Subject: [PATCH 2/6] chore(workflow): only keep slim image --- .github/workflows/docker-build.yaml | 636 +--------------------------- 1 file changed, 1 insertion(+), 635 deletions(-) diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml index d28475a338..108f180a09 100644 --- a/.github/workflows/docker-build.yaml +++ b/.github/workflows/docker-build.yaml @@ -12,418 +12,6 @@ env: REGISTRY: ghcr.io jobs: - build-main-image: - runs-on: ${{ matrix.runner }} - permissions: - contents: read - packages: write - strategy: - fail-fast: false - matrix: - include: - - platform: linux/amd64 - runner: ubuntu-latest - - platform: linux/arm64 - runner: ubuntu-24.04-arm - - steps: - # GitHub Packages requires the entire repository name to be in lowercase - # although the repository owner has a lowercase username, this prevents some people from running actions after forking - - name: Set repository and image name to lowercase - run: | - echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV} - echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV} - env: - IMAGE_NAME: '${{ github.repository }}' - - - name: Prepare - run: | - platform=${{ matrix.platform }} - echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - - - name: Checkout repository - uses: actions/checkout@v5 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to the Container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata for Docker images (default latest tag) - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.FULL_IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=tag - type=sha,prefix=git- - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - flavor: | - latest=${{ github.ref == 'refs/heads/main' }} - - - name: Extract metadata for Docker cache - id: cache-meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.FULL_IMAGE_NAME }} - tags: | - type=ref,event=branch - ${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }} - flavor: | - prefix=cache-${{ matrix.platform }}- - latest=false - - - name: Build Docker image (latest) - uses: docker/build-push-action@v5 - id: build - with: - context: . - push: true - platforms: ${{ matrix.platform }} - labels: ${{ steps.meta.outputs.labels }} - outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true - cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }} - cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max - build-args: | - BUILD_HASH=${{ github.sha }} - - - name: Export digest - run: | - mkdir -p /tmp/digests - digest="${{ steps.build.outputs.digest }}" - touch "/tmp/digests/${digest#sha256:}" - - - name: Upload digest - uses: actions/upload-artifact@v4 - with: - name: digests-main-${{ env.PLATFORM_PAIR }} - path: /tmp/digests/* - if-no-files-found: error - retention-days: 1 - - build-cuda-image: - runs-on: ${{ matrix.runner }} - permissions: - contents: read - packages: write - strategy: - fail-fast: false - matrix: - include: - - platform: linux/amd64 - runner: ubuntu-latest - - platform: linux/arm64 - runner: ubuntu-24.04-arm - - steps: - # GitHub Packages requires the entire repository name to be in lowercase - # although the repository owner has a lowercase username, this prevents some people from running actions after forking - - name: Set repository and image name to lowercase - run: | - echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV} - echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV} - env: - IMAGE_NAME: '${{ github.repository }}' - - - name: Prepare - run: | - platform=${{ matrix.platform }} - echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - - - name: Delete huge unnecessary tools folder - run: rm -rf /opt/hostedtoolcache - - - name: Checkout repository - uses: actions/checkout@v5 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to the Container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata for Docker images (cuda tag) - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.FULL_IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=tag - type=sha,prefix=git- - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=cuda - flavor: | - latest=${{ github.ref == 'refs/heads/main' }} - suffix=-cuda,onlatest=true - - - name: Extract metadata for Docker cache - id: cache-meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.FULL_IMAGE_NAME }} - tags: | - type=ref,event=branch - ${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }} - flavor: | - prefix=cache-cuda-${{ matrix.platform }}- - latest=false - - - name: Build Docker image (cuda) - uses: docker/build-push-action@v5 - id: build - with: - context: . - push: true - platforms: ${{ matrix.platform }} - labels: ${{ steps.meta.outputs.labels }} - outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true - cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }} - cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max - build-args: | - BUILD_HASH=${{ github.sha }} - USE_CUDA=true - - - name: Export digest - run: | - mkdir -p /tmp/digests - digest="${{ steps.build.outputs.digest }}" - touch "/tmp/digests/${digest#sha256:}" - - - name: Upload digest - uses: actions/upload-artifact@v4 - with: - name: digests-cuda-${{ env.PLATFORM_PAIR }} - path: /tmp/digests/* - if-no-files-found: error - retention-days: 1 - - build-cuda126-image: - runs-on: ${{ matrix.runner }} - permissions: - contents: read - packages: write - strategy: - fail-fast: false - matrix: - include: - - platform: linux/amd64 - runner: ubuntu-latest - - platform: linux/arm64 - runner: ubuntu-24.04-arm - - steps: - # GitHub Packages requires the entire repository name to be in lowercase - # although the repository owner has a lowercase username, this prevents some people from running actions after forking - - name: Set repository and image name to lowercase - run: | - echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV} - echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV} - env: - IMAGE_NAME: '${{ github.repository }}' - - - name: Prepare - run: | - platform=${{ matrix.platform }} - echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - - - name: Delete huge unnecessary tools folder - run: rm -rf /opt/hostedtoolcache - - - name: Checkout repository - uses: actions/checkout@v5 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to the Container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata for Docker images (cuda126 tag) - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.FULL_IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=tag - type=sha,prefix=git- - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=cuda126 - flavor: | - latest=${{ github.ref == 'refs/heads/main' }} - suffix=-cuda126,onlatest=true - - - name: Extract metadata for Docker cache - id: cache-meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.FULL_IMAGE_NAME }} - tags: | - type=ref,event=branch - ${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }} - flavor: | - prefix=cache-cuda126-${{ matrix.platform }}- - latest=false - - - name: Build Docker image (cuda126) - uses: docker/build-push-action@v5 - id: build - with: - context: . - push: true - platforms: ${{ matrix.platform }} - labels: ${{ steps.meta.outputs.labels }} - outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true - cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }} - cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max - build-args: | - BUILD_HASH=${{ github.sha }} - USE_CUDA=true - USE_CUDA_VER=cu126 - - - name: Export digest - run: | - mkdir -p /tmp/digests - digest="${{ steps.build.outputs.digest }}" - touch "/tmp/digests/${digest#sha256:}" - - - name: Upload digest - uses: actions/upload-artifact@v4 - with: - name: digests-cuda126-${{ env.PLATFORM_PAIR }} - path: /tmp/digests/* - if-no-files-found: error - retention-days: 1 - - build-ollama-image: - runs-on: ${{ matrix.runner }} - permissions: - contents: read - packages: write - strategy: - fail-fast: false - matrix: - include: - - platform: linux/amd64 - runner: ubuntu-latest - - platform: linux/arm64 - runner: ubuntu-24.04-arm - - steps: - # GitHub Packages requires the entire repository name to be in lowercase - # although the repository owner has a lowercase username, this prevents some people from running actions after forking - - name: Set repository and image name to lowercase - run: | - echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV} - echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV} - env: - IMAGE_NAME: '${{ github.repository }}' - - - name: Prepare - run: | - platform=${{ matrix.platform }} - echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - - - name: Checkout repository - uses: actions/checkout@v5 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to the Container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata for Docker images (ollama tag) - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.FULL_IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=tag - type=sha,prefix=git- - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=ollama - flavor: | - latest=${{ github.ref == 'refs/heads/main' }} - suffix=-ollama,onlatest=true - - - name: Extract metadata for Docker cache - id: cache-meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.FULL_IMAGE_NAME }} - tags: | - type=ref,event=branch - ${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }} - flavor: | - prefix=cache-ollama-${{ matrix.platform }}- - latest=false - - - name: Build Docker image (ollama) - uses: docker/build-push-action@v5 - id: build - with: - context: . - push: true - platforms: ${{ matrix.platform }} - labels: ${{ steps.meta.outputs.labels }} - outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true - cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }} - cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max - build-args: | - BUILD_HASH=${{ github.sha }} - USE_OLLAMA=true - - - name: Export digest - run: | - mkdir -p /tmp/digests - digest="${{ steps.build.outputs.digest }}" - touch "/tmp/digests/${digest#sha256:}" - - - name: Upload digest - uses: actions/upload-artifact@v4 - with: - name: digests-ollama-${{ env.PLATFORM_PAIR }} - path: /tmp/digests/* - if-no-files-found: error - retention-days: 1 - build-slim-image: runs-on: ${{ matrix.runner }} permissions: @@ -525,229 +113,6 @@ jobs: path: /tmp/digests/* if-no-files-found: error retention-days: 1 - - merge-main-images: - runs-on: ubuntu-latest - needs: [build-main-image] - steps: - # GitHub Packages requires the entire repository name to be in lowercase - # although the repository owner has a lowercase username, this prevents some people from running actions after forking - - name: Set repository and image name to lowercase - run: | - echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV} - echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV} - env: - IMAGE_NAME: '${{ github.repository }}' - - - name: Download digests - uses: actions/download-artifact@v5 - with: - pattern: digests-main-* - path: /tmp/digests - merge-multiple: true - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to the Container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata for Docker images (default latest tag) - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.FULL_IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=tag - type=sha,prefix=git- - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - flavor: | - latest=${{ github.ref == 'refs/heads/main' }} - - - name: Create manifest list and push - working-directory: /tmp/digests - run: | - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ env.FULL_IMAGE_NAME }}@sha256:%s ' *) - - - name: Inspect image - run: | - docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }} - - merge-cuda-images: - runs-on: ubuntu-latest - needs: [build-cuda-image] - steps: - # GitHub Packages requires the entire repository name to be in lowercase - # although the repository owner has a lowercase username, this prevents some people from running actions after forking - - name: Set repository and image name to lowercase - run: | - echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV} - echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV} - env: - IMAGE_NAME: '${{ github.repository }}' - - - name: Download digests - uses: actions/download-artifact@v5 - with: - pattern: digests-cuda-* - path: /tmp/digests - merge-multiple: true - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to the Container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata for Docker images (default latest tag) - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.FULL_IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=tag - type=sha,prefix=git- - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=cuda - flavor: | - latest=${{ github.ref == 'refs/heads/main' }} - suffix=-cuda,onlatest=true - - - name: Create manifest list and push - working-directory: /tmp/digests - run: | - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ env.FULL_IMAGE_NAME }}@sha256:%s ' *) - - - name: Inspect image - run: | - docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }} - - merge-cuda126-images: - runs-on: ubuntu-latest - needs: [build-cuda126-image] - steps: - # GitHub Packages requires the entire repository name to be in lowercase - # although the repository owner has a lowercase username, this prevents some people from running actions after forking - - name: Set repository and image name to lowercase - run: | - echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV} - echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV} - env: - IMAGE_NAME: '${{ github.repository }}' - - - name: Download digests - uses: actions/download-artifact@v5 - with: - pattern: digests-cuda126-* - path: /tmp/digests - merge-multiple: true - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to the Container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata for Docker images (default latest tag) - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.FULL_IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=tag - type=sha,prefix=git- - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=cuda126 - flavor: | - latest=${{ github.ref == 'refs/heads/main' }} - suffix=-cuda126,onlatest=true - - - name: Create manifest list and push - working-directory: /tmp/digests - run: | - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ env.FULL_IMAGE_NAME }}@sha256:%s ' *) - - - name: Inspect image - run: | - docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }} - - merge-ollama-images: - runs-on: ubuntu-latest - needs: [build-ollama-image] - steps: - # GitHub Packages requires the entire repository name to be in lowercase - # although the repository owner has a lowercase username, this prevents some people from running actions after forking - - name: Set repository and image name to lowercase - run: | - echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV} - echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV} - env: - IMAGE_NAME: '${{ github.repository }}' - - - name: Download digests - uses: actions/download-artifact@v5 - with: - pattern: digests-ollama-* - path: /tmp/digests - merge-multiple: true - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to the Container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata for Docker images (default ollama tag) - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.FULL_IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=tag - type=sha,prefix=git- - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=ollama - flavor: | - latest=${{ github.ref == 'refs/heads/main' }} - suffix=-ollama,onlatest=true - - - name: Create manifest list and push - working-directory: /tmp/digests - run: | - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ env.FULL_IMAGE_NAME }}@sha256:%s ' *) - - - name: Inspect image - run: | - docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }} - merge-slim-images: runs-on: ubuntu-latest needs: [build-slim-image] @@ -803,3 +168,4 @@ jobs: - name: Inspect image run: | docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }} + From 37a3c50bca2d4df966820b3d5177d582ccfc17dc Mon Sep 17 00:00:00 2001 From: U8F69 Date: Wed, 28 Jan 2026 20:43:17 +0800 Subject: [PATCH 3/6] fix(chat): refactor chat API error handling and response processing --- src/lib/components/chat/Chat.svelte | 163 +++++++++++++--------------- 1 file changed, 77 insertions(+), 86 deletions(-) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index f80513c799..ff41dfe472 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -1945,102 +1945,93 @@ } } - let res; - try { - res = await generateOpenAIChatCompletion( - localStorage.token, - { - stream: stream, - model: model.id, - messages: messages, - params: { - ...$settings?.params, - ...params, - stop: - (params?.stop ?? $settings?.params?.stop ?? undefined) - ? ( - params?.stop.split(',').map((token) => token.trim()) ?? $settings.params.stop - ).map((str) => - decodeURIComponent(JSON.parse('"' + str.replace(/\"/g, '\\"') + '"')) - ) - : undefined - }, - - files: (files?.length ?? 0) > 0 ? files : undefined, - - filter_ids: selectedFilterIds.length > 0 ? selectedFilterIds : undefined, - tool_ids: toolIds.length > 0 ? toolIds : undefined, - tool_servers: ($toolServers ?? []).filter( - (server, idx) => toolServerIds.includes(idx) || toolServerIds.includes(server?.id) - ), - features: getFeatures(), - variables: { - ...getPromptVariables($user?.name, $settings?.userLocation ? userLocation : undefined) - }, - model_item: $models.find((m) => m.id === model.id), - - session_id: $socket?.id, - chat_id: $chatId, + const res = await generateOpenAIChatCompletion( + localStorage.token, + { + stream: stream, + model: model.id, + messages: messages, + params: { + ...$settings?.params, + ...params, + stop: + (params?.stop ?? $settings?.params?.stop ?? undefined) + ? (params?.stop.split(',').map((token) => token.trim()) ?? $settings.params.stop).map( + (str) => decodeURIComponent(JSON.parse('"' + str.replace(/\"/g, '\\"') + '"')) + ) + : undefined + }, - id: responseMessageId, - parent_id: userMessage?.id ?? null, - parent_message: userMessage, - - background_tasks: { - ...(!$temporaryChatEnabled && - (messages.length == 1 || - (messages.length == 2 && - messages.at(0)?.role === 'system' && - messages.at(1)?.role === 'user')) && - (selectedModels[0] === model.id || atSelectedModel !== undefined) - ? { - title_generation: $settings?.title?.auto ?? true, - tags_generation: $settings?.autoTags ?? true - } - : {}), - follow_up_generation: $settings?.autoFollowUps ?? true - }, + files: (files?.length ?? 0) > 0 ? files : undefined, - ...(stream && (model.info?.meta?.capabilities?.usage ?? false) + filter_ids: selectedFilterIds.length > 0 ? selectedFilterIds : undefined, + tool_ids: toolIds.length > 0 ? toolIds : undefined, + tool_servers: ($toolServers ?? []).filter( + (server, idx) => toolServerIds.includes(idx) || toolServerIds.includes(server?.id) + ), + features: getFeatures(), + variables: { + ...getPromptVariables($user?.name, $settings?.userLocation ? userLocation : undefined) + }, + model_item: $models.find((m) => m.id === model.id), + + session_id: $socket?.id, + chat_id: $chatId, + + id: responseMessageId, + parent_id: userMessage?.id ?? null, + parent_message: userMessage, + + background_tasks: { + ...(!$temporaryChatEnabled && + (messages.length == 1 || + (messages.length == 2 && + messages.at(0)?.role === 'system' && + messages.at(1)?.role === 'user')) && + (selectedModels[0] === model.id || atSelectedModel !== undefined) ? { - stream_options: { - include_usage: true - } + title_generation: $settings?.title?.auto ?? true, + tags_generation: $settings?.autoTags ?? true } - : {}) + : {}), + follow_up_generation: $settings?.autoFollowUps ?? true }, - `${WEBUI_BASE_URL}/api` - ).catch(async (error) => { - console.log(error); - - let errorMessage = error; - if (error?.error?.message) { - errorMessage = error.error.message; - } else if (error?.message) { - errorMessage = error.message; - } - if (typeof errorMessage === 'object') { - errorMessage = $i18n.t(`Uh-oh! There was an issue with the response.`); - } + ...(stream && (model.info?.meta?.capabilities?.usage ?? false) + ? { + stream_options: { + include_usage: true + } + } + : {}) + }, + `${WEBUI_BASE_URL}/api` + ).catch(async (error) => { + console.log(error); + + let errorMessage = error; + if (error?.error?.message) { + errorMessage = error.error.message; + } else if (error?.message) { + errorMessage = error.message; + } - toast.error(`${errorMessage}`); - responseMessage.error = { - content: error - }; + if (typeof errorMessage === 'object') { + errorMessage = $i18n.t(`Uh-oh! There was an issue with the response.`); + } - responseMessage.done = true; + toast.error(`${errorMessage}`); + responseMessage.error = { + content: error + }; - history.messages[responseMessageId] = responseMessage; - history.currentId = responseMessageId; + responseMessage.done = true; - return null; - }); - } catch (e) { - console.error(e); - await handleOpenAIError(e, responseMessage); - return; - } + history.messages[responseMessageId] = responseMessage; + history.currentId = responseMessageId; + + return null; + }); if (res) { if (res.error) { From d9c74cb9bd97006636627fb6ec68a4bd17b63622 Mon Sep 17 00:00:00 2001 From: U8F69 Date: Wed, 28 Jan 2026 21:04:54 +0800 Subject: [PATCH 4/6] fix(chat): improve error handling in chat operations --- CHANGELOG_EXTRA.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- src/lib/apis/index.ts | 26 +++++++++++++++++++++++++ src/lib/components/chat/Chat.svelte | 30 ++++++++++++++++------------- 5 files changed, 47 insertions(+), 17 deletions(-) diff --git a/CHANGELOG_EXTRA.md b/CHANGELOG_EXTRA.md index be857c3f76..78763fa968 100644 --- a/CHANGELOG_EXTRA.md +++ b/CHANGELOG_EXTRA.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.7.2.2] - 2026.01.28 +## [0.7.2.3] - 2026.01.28 ### Changed diff --git a/package-lock.json b/package-lock.json index 089ecf4e59..3dcd2f03b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "open-webui", - "version": "0.7.2.2", + "version": "0.7.2.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "open-webui", - "version": "0.7.2.2", + "version": "0.7.2.3", "dependencies": { "@azure/msal-browser": "^4.5.0", "@codemirror/lang-javascript": "^6.2.2", diff --git a/package.json b/package.json index b3d6b5b558..ae2274af60 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "open-webui", - "version": "0.7.2.2", + "version": "0.7.2.3", "private": true, "scripts": { "dev": "npm run pyodide:fetch && vite dev --host", diff --git a/src/lib/apis/index.ts b/src/lib/apis/index.ts index 8f35fbf881..ff2cde636c 100644 --- a/src/lib/apis/index.ts +++ b/src/lib/apis/index.ts @@ -1,6 +1,32 @@ import { WEBUI_BASE_URL } from '$lib/constants'; import { convertOpenApiToToolPayload } from '$lib/utils'; import { getOpenAIModelsDirect } from './openai'; +import { toast } from 'svelte-sonner'; + +type UnknownError = { + code?: number; + trace?: string; + next?: string; + detail?: string; + error_message?: string; + message?: string; +}; + +export const handleError = (e: UnknownError | string) => { + console.error(e); + if (typeof e === 'object') { + const errorMsg = e?.detail || e?.error_message || e?.message || JSON.stringify(e); + toast.error(errorMsg); + if (e?.code && e?.code >= 400 && e?.next) { + setTimeout(() => { + window.location.replace(e?.next); + }, 1800); + } + } else { + toast.error(e); + } + throw e; +}; export const getModels = async ( token: string = '', diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index ff41dfe472..9b832c4046 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -77,7 +77,8 @@ chatAction, generateMoACompletion, stopTask, - getTaskIdsByChatId + getTaskIdsByChatId, + handleError } from '$lib/apis'; import { getTools } from '$lib/apis/tools'; import { uploadFile } from '$lib/apis/files'; @@ -885,7 +886,6 @@ artifactContents.set(contents); }; - ////////////////////////// // Web functions ////////////////////////// @@ -2315,18 +2315,22 @@ }; const saveChatHandler = async (_chatId, history) => { - if ($chatId == _chatId) { - if (!$temporaryChatEnabled) { - chat = await updateChatById(localStorage.token, _chatId, { - models: selectedModels, - history: history, - messages: createMessagesList(history, history.currentId), - params: params, - files: chatFiles - }); - currentChatPage.set(1); - await chats.set(await getChatList(localStorage.token, $currentChatPage)); + try { + if ($chatId == _chatId) { + if (!$temporaryChatEnabled) { + chat = await updateChatById(localStorage.token, _chatId, { + models: selectedModels, + history: history, + messages: createMessagesList(history, history.currentId), + params: params, + files: chatFiles + }); + currentChatPage.set(1); + await chats.set(await getChatList(localStorage.token, $currentChatPage)); + } } + } catch (e) { + handleError(e); } }; From 08889e732289dc1143fc66ae049723ebe172b56c Mon Sep 17 00:00:00 2001 From: U8F69 Date: Wed, 28 Jan 2026 21:19:36 +0800 Subject: [PATCH 5/6] fix(chat): update error handling to reload on API failures --- CHANGELOG_EXTRA.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- src/lib/apis/index.ts | 4 +--- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/CHANGELOG_EXTRA.md b/CHANGELOG_EXTRA.md index 78763fa968..f2a05c7a13 100644 --- a/CHANGELOG_EXTRA.md +++ b/CHANGELOG_EXTRA.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.7.2.3] - 2026.01.28 +## [0.7.2.4] - 2026.01.28 ### Changed diff --git a/package-lock.json b/package-lock.json index 3dcd2f03b4..2e0565c38d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "open-webui", - "version": "0.7.2.3", + "version": "0.7.2.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "open-webui", - "version": "0.7.2.3", + "version": "0.7.2.4", "dependencies": { "@azure/msal-browser": "^4.5.0", "@codemirror/lang-javascript": "^6.2.2", diff --git a/package.json b/package.json index ae2274af60..702172f548 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "open-webui", - "version": "0.7.2.3", + "version": "0.7.2.4", "private": true, "scripts": { "dev": "npm run pyodide:fetch && vite dev --host", diff --git a/src/lib/apis/index.ts b/src/lib/apis/index.ts index ff2cde636c..58827c8980 100644 --- a/src/lib/apis/index.ts +++ b/src/lib/apis/index.ts @@ -18,9 +18,7 @@ export const handleError = (e: UnknownError | string) => { const errorMsg = e?.detail || e?.error_message || e?.message || JSON.stringify(e); toast.error(errorMsg); if (e?.code && e?.code >= 400 && e?.next) { - setTimeout(() => { - window.location.replace(e?.next); - }, 1800); + window.location.reload(); } } else { toast.error(e); From e33779ba6d9d32b37ce14dc7ba33238213d49fd3 Mon Sep 17 00:00:00 2001 From: U8F69 Date: Wed, 28 Jan 2026 21:45:25 +0800 Subject: [PATCH 6/6] fix(chat): enhance error handling in chat initialization --- CHANGELOG_EXTRA.md | 2 +- package-lock.json | 4 +- package.json | 2 +- src/lib/components/chat/Chat.svelte | 64 +++++++++++++++-------------- 4 files changed, 38 insertions(+), 34 deletions(-) diff --git a/CHANGELOG_EXTRA.md b/CHANGELOG_EXTRA.md index f2a05c7a13..081243b4b8 100644 --- a/CHANGELOG_EXTRA.md +++ b/CHANGELOG_EXTRA.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.7.2.4] - 2026.01.28 +## [0.7.2.5] - 2026.01.28 ### Changed diff --git a/package-lock.json b/package-lock.json index 2e0565c38d..9a4b2d39ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "open-webui", - "version": "0.7.2.4", + "version": "0.7.2.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "open-webui", - "version": "0.7.2.4", + "version": "0.7.2.5", "dependencies": { "@azure/msal-browser": "^4.5.0", "@codemirror/lang-javascript": "^6.2.2", diff --git a/package.json b/package.json index 702172f548..b7766f922d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "open-webui", - "version": "0.7.2.4", + "version": "0.7.2.5", "private": true, "scripts": { "dev": "npm run pyodide:fetch && vite dev --host", diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 9b832c4046..e71ae170ca 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -2275,43 +2275,47 @@ }; const initChatHandler = async (history) => { - let _chatId = $chatId; + try { + let _chatId = $chatId; - if (!$temporaryChatEnabled) { - chat = await createNewChat( - localStorage.token, - { - id: _chatId, - title: $i18n.t('New Chat'), - models: selectedModels, - system: $settings.system ?? undefined, - params: params, - history: history, - messages: createMessagesList(history, history.currentId), - tags: [], - timestamp: Date.now() - }, - $selectedFolder?.id - ); + if (!$temporaryChatEnabled) { + chat = await createNewChat( + localStorage.token, + { + id: _chatId, + title: $i18n.t('New Chat'), + models: selectedModels, + system: $settings.system ?? undefined, + params: params, + history: history, + messages: createMessagesList(history, history.currentId), + tags: [], + timestamp: Date.now() + }, + $selectedFolder?.id + ); - _chatId = chat.id; - await chatId.set(_chatId); + _chatId = chat.id; + await chatId.set(_chatId); - window.history.replaceState(history.state, '', `/c/${_chatId}`); + window.history.replaceState(history.state, '', `/c/${_chatId}`); - await tick(); + await tick(); - await chats.set(await getChatList(localStorage.token, $currentChatPage)); - currentChatPage.set(1); + await chats.set(await getChatList(localStorage.token, $currentChatPage)); + currentChatPage.set(1); - selectedFolder.set(null); - } else { - _chatId = `local:${$socket?.id}`; // Use socket id for temporary chat - await chatId.set(_chatId); - } - await tick(); + selectedFolder.set(null); + } else { + _chatId = `local:${$socket?.id}`; // Use socket id for temporary chat + await chatId.set(_chatId); + } + await tick(); - return _chatId; + return _chatId; + } catch (e) { + handleError(e); + } }; const saveChatHandler = async (_chatId, history) => {