Skip to content

fix: guard the dashboard's docker icon onerror fallback - #2709

Open
Joly0 wants to merge 1 commit into
unraid:masterfrom
Joly0:fix/dashboard-icon-onerror-loop
Open

fix: guard the dashboard's docker icon onerror fallback#2709
Joly0 wants to merge 1 commit into
unraid:masterfrom
Joly0:fix/dashboard-icon-onerror-loop

Conversation

@Joly0

@Joly0 Joly0 commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #2693, which added this guard to DockerContainers.php but not to the dashboard's copy of the same line in DashboardApps.php.

The dashboard renders every container icon like this:

<img src='$icon?...' class='img' onerror=this.src='/plugins/dynamix.docker.manager/images/question.png';>

For a container with no icon, $info['icon'] is already the question.png path (set in DockerClient.php:346), so src and the onerror target are the same file. If question.png is missing, the handler reassigns a URL that also 404s, which fires onerror again, and nothing ever detaches it.

I ran into this after question.png was deleted on my server — the bug fixed in #2693. I'm on 7.3.2, so the backport in #2708 hasn't reached me yet. nginx's error log for the two minutes I had the dashboard open:

...question.png?    (the src attribute)      5 requests
...question.png     (the onerror target) 18,322 requests

The ? is empty because filemtime() returns false for the missing file, which is what makes the two URLs distinguishable in the log. That 5 : 18,322 split is the retry loop — polling would keep the two roughly proportional.

The change is the same one already merged for DockerContainers.php: quote the attribute and set this.onerror=null before reassigning src. The onerror fragment is now byte-identical between the two files. A missing fallback then costs one extra failed request per image instead of an unbounded loop.

Containers with a working icon are unaffected, and one whose icon 404s still falls back to question.png and renders it. Only the pathological case is capped.

Testing

DashboardApps.php is byte-identical between 7.3.2 and master at d3898259, so I tested the patched master file on a 7.3.2 box.

php -l clean. Rendered the expression with the file missing, before and after:

before: <img src='...question.png?' class='img' onerror=this.src='...question.png';>
after:  <img src='...question.png?' class='img' onerror="this.onerror=null;this.src='...question.png';">

I also confirmed the underlying deletion end-to-end on 7.3.2 before patching: with a throwaway icon-less container registered in docker.json, removing it from the Docker tab (Events.phpremoveContainer() with cache=1) deleted question.png at the moment of the click, which inotify caught. That part is already handled by #2693/#2708 — this PR only caps the fallout when the file is missing for any reason.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved Docker image fallback handling to prevent repeated error events when a container image fails to load.
    • Failed images now reliably display the default question-mark icon.

The dashboard renders each container icon with an onerror handler that
falls back to question.png, but for containers without an icon the src
is already question.png. When that file goes missing the handler just
reassigns the same dead URL, so the browser retries it forever.

I hit this on my own server after the icon disappeared: 18,322 requests
for the fallback in two minutes from a single open dashboard, against 5
for the initial src.

DockerContainers.php got this exact guard in unraid#2693. The dashboard copy
of the same line was missed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

🔧 PR Test Plugin Available

A test plugin has been generated for this PR that includes the modified files.

Version: 2026.07.31.0625
Build: View Workflow Run

📥 Installation Instructions:

Install via Unraid Web UI:

  1. Go to Plugins → Install Plugin
  2. Copy and paste this URL:
https://preview.dl.unraid.net/pr-plugins/pr-2709/webgui-pr-2709.plg
  1. Click Install

Alternative: Direct Download

⚠️ Important Notes:

  • Testing only: This plugin is for testing PR changes
  • Backup included: Original files are automatically backed up
  • Easy removal: Files are restored when plugin is removed
  • Conflicts: Remove this plugin before installing production updates
  • Post-merge behavior: This preview stays available after merge until preview storage expires or it is manually cleaned up

📝 Modified Files:

Click to expand file list
emhttp/plugins/dynamix/include/DashboardApps.php

🔄 To Remove:

Navigate to Plugins → Installed Plugins and remove webgui-pr-2709, or run:

plugin remove webgui-pr-2709

🤖 This comment is automatically generated and will be updated with each new push to this PR.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9a507a2b-1c2f-44b0-8e73-5236d4651d9b

📥 Commits

Reviewing files that changed from the base of the PR and between d389825 and 73a6182.

📒 Files selected for processing (1)
  • emhttp/plugins/dynamix/include/DashboardApps.php

Walkthrough

The Docker image fallback handler now clears this.onerror before it assigns the default question-mark icon.

Changes

Docker image fallback

Layer / File(s) Summary
Fallback handler
emhttp/plugins/dynamix/include/DashboardApps.php
The onerror handler now sets this.onerror to null before assigning the fallback image source.

Estimated code review effort: 1 (Trivial) | ~2 minutes

Possibly related PRs

  • unraid/webgui#2693: Updates a matching Docker image onerror fallback handler in another file.

Poem

A rabbit saw the image fail,
Then stopped the error’s looping trail.
The question mark now shines in place,
With tidy code and steady grace.
Hop, hop—fallback wins the race!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the Docker icon fallback guard added to the dashboard.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant