-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Description
Please verify that this bug has NOT been raised before.
- I checked and didn't find a similar issue
Describe the bug*
Thank you for the awesome project! I am having difficulty installing a plugin through the web UI when the plugin is hosted in a custom registry or is a .whl file (or both).
In the "Install Plugin" window under "Source URL", I can see a hint which says "Source for the package - this can be a custom registry or a VCS path" so this seems to be possible.
Setup:
I am using a clean docker install of Inventree 1.2.3
I have a PEP 503 Simple Repository hosted at https://my-custom-domain.com/python such that the package I want to install has the following URL:
What are the correct values to put into the "Package Name" and "Source URL" of the "Install Plugin" web UI window?
I have tried the following:
Option 1
This is what I thought should work. But, the name of the package is missing for pip to install.
Package Name: "my_custom_plugin"
Source URL: "https://my-custom-domain.com/python"
I get error in the UI: ERROR: You must give at least one requirement to install (see "pip help install"). In the logs I get:
inventree-server | 172.24.0.1 - - [04/Mar/2026:15:23:11 +0000] "GET /api/notifications/?read=false&limit=1 HTTP/1.1" 200 52 "http://inventree.localhost/web/settings/admin/plugin" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36"
inventree-server | 2026-03-04T15:23:29.378887Z [error ] Command '['/usr/local/bin/python3.11', '-m', 'pip', 'install', '-U', '--disable-pip-version-check', '-i', 'https://my-custom-domain.com/python']' returned non-zero exit status 1. [inventree] ip=172.24.0.1 request_id=20dcbd5c-ec22-4306-bbb1-56022c5311fe user_id=1
inventree-server | 2026-03-04 15:23:29,378 ERROR {'event': CalledProcessError(1, ['/usr/local/bin/python3.11', '-m', 'pip', 'install', '-U', '--disable-pip-version-check', '-i', 'https://my-custom-domain.com/python']), 'ip': '172.24.0.1', 'request_id': '20dcbd5c-ec22-4306-bbb1-56022c5311fe', 'user_id': 1, 'timestamp': '2026-03-04T15:23:29.378887Z', 'logger': 'inventree', 'level': 'error'}
inventree-server | /root/.local/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1612: RuntimeWarning: DateTimeField NotificationEntry.updated received a naive datetime (2026-03-03 00:00:00) while time zone support is active.
inventree-server | warnings.warn(
inventree-server | 2026-03-04T15:23:29.411592Z [error ] Pip command failed: ERROR: You must give at least one requirement to install (see "pip help install")
inventree-server | [inventree] ip=172.24.0.1 request_id=20dcbd5c-ec22-4306-bbb1-56022c5311fe user_id=1
inventree-server | 2026-03-04 15:23:29,411 ERROR {'event': 'Pip command failed: ERROR: You must give at least one requirement to install (see "pip help install")\n', 'ip': '172.24.0.1', 'request_id': '20dcbd5c-ec22-4306-bbb1-56022c5311fe', 'user_id': 1, 'timestamp': '2026-03-04T15:23:29.411592Z', 'logger': 'inventree', 'level': 'error'}
inventree-server | 2026-03-04T15:23:29.412130Z [warning ] request_finished [django_structlog.middlewares.request] code=400 ip=172.24.0.1 request='POST /api/plugins/install/' request_id=20dcbd5c-ec22-4306-bbb1-56022c5311fe user_id=1
Option 2
Trying to give the full URL of the wheel file.
Package Name: "https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl"
Source URL: ""
No error message in the UI, in the logs I get:
inventree-server | 2026-03-04T15:26:08.736767Z [error ] Command '['/usr/local/bin/python3.11', '-m', 'pip', 'show', 'https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl']' returned non-zero exit status 1. [inventree] ip=172.24.0.1 request_id=754eb1ac-7be3-4112-b774-df5f6e25f6cf user_id=1
inventree-server | 2026-03-04 15:26:08,736 ERROR {'event': CalledProcessError(1, ['/usr/local/bin/python3.11', '-m', 'pip', 'show', 'https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl']), 'ip': '172.24.0.1', 'request_id': '754eb1ac-7be3-4112-b774-df5f6e25f6cf', 'user_id': 1, 'timestamp': '2026-03-04T15:26:08.736767Z', 'logger': 'inventree', 'level': 'error'}
inventree-server | 2026-03-04T15:26:08.760912Z [error ] Plugin lookup failed: WARNING: Package(s) not found: https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl
inventree-server | [inventree] ip=172.24.0.1 request_id=754eb1ac-7be3-4112-b774-df5f6e25f6cf user_id=1
inventree-server | Traceback (most recent call last):
inventree-server | File "/home/inventree/src/backend/InvenTree/plugin/installer.py", line 84, in get_install_info
inventree-server | result = pip_command('show', packagename)
inventree-server | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
inventree-server | File "/home/inventree/src/backend/InvenTree/plugin/installer.py", line 38, in pip_command
inventree-server | return subprocess.check_output(
inventree-server | ^^^^^^^^^^^^^^^^^^^^^^^^
inventree-server | File "/usr/local/lib/python3.11/subprocess.py", line 466, in check_output
inventree-server | return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
inventree-server | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
inventree-server | File "/usr/local/lib/python3.11/subprocess.py", line 571, in run
inventree-server | raise CalledProcessError(retcode, process.args,
inventree-server | subprocess.CalledProcessError: Command '['/usr/local/bin/python3.11', '-m', 'pip', 'show', 'https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl']' returned non-zero exit status 1.
inventree-server | 2026-03-04 15:26:08,761 ERROR {'event': 'Plugin lookup failed: WARNING: Package(s) not found: https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl\n', 'ip': '172.24.0.1', 'request_id': '754eb1ac-7be3-4112-b774-df5f6e25f6cf', 'user_id': 1, 'timestamp': '2026-03-04T15:26:08.760912Z', 'logger': 'inventree', 'level': 'error', 'exception': 'Traceback (most recent call last):\n File "/home/inventree/src/backend/InvenTree/plugin/installer.py", line 84, in get_install_info\n result = pip_command(\'show\', packagename)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File "/home/inventree/src/backend/InvenTree/plugin/installer.py", line 38, in pip_command\n return subprocess.check_output(\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File "/usr/local/lib/python3.11/subprocess.py", line 466, in check_output\n return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File "/usr/local/lib/python3.11/subprocess.py", line 571, in run\n raise CalledProcessError(retcode, process.args,\nsubprocess.CalledProcessError: Command \'[\'/usr/local/bin/python3.11\', \'-m\', \'pip\', \'show\', \'https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl\']\' returned non-zero exit status 1.'}
inventree-server | 172.24.0.1 - - [04/Mar/2026:15:26:08 +0000] "POST /api/plugins/install/ HTTP/1.1" 201 1157 "http://inventree.localhost/web/settings/admin/plugin" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36"
Option 3
This is the option which gets me the closest. But, ==1.1.2 gets appended to the URL which results in a 404 error.
Package Name: "my_custom_plugin @ https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl"
Source URL: ""
No error messages in UI, in logs:
inventree-server | 2026-03-04T15:27:52.420349Z [error ] Plugin file installation failed: Collecting my_custom_plugin@ https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl==1.1.2 (from -r /home/inventree/data/plugins.txt (line 3))
inventree-server | ERROR: HTTP error 404 while getting https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl==1.1.2
inventree-server | ERROR: Could not install requirement my_custom_plugin@ https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl==1.1.2 from https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl==1.1.2 (from -r /home/inventree/data/plugins.txt (line 3)) because of HTTP error 404 Client Error: Not Found for url: https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl==1.1.2 for URL https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl==1.1.2
inventree-server | [inventree] ip=172.24.0.1 request_id=8096f46c-4f30-4af2-ac04-26379e699d13 user_id=1
inventree-server | Traceback (most recent call last):
inventree-server | File "/home/inventree/src/backend/InvenTree/plugin/installer.py", line 140, in install_plugins_file
inventree-server | pip_command(*cmd)
inventree-server | File "/home/inventree/src/backend/InvenTree/plugin/installer.py", line 38, in pip_command
inventree-server | return subprocess.check_output(
inventree-server | ^^^^^^^^^^^^^^^^^^^^^^^^
inventree-server | File "/usr/local/lib/python3.11/subprocess.py", line 466, in check_output
inventree-server | return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
inventree-server | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
inventree-server | File "/usr/local/lib/python3.11/subprocess.py", line 571, in run
inventree-server | raise CalledProcessError(retcode, process.args,
inventree-server | subprocess.CalledProcessError: Command '['/usr/local/bin/python3.11', '-m', 'pip', 'install', '--disable-pip-version-check', '-U', '-r', '/home/inventree/data/plugins.txt']' returned non-zero exit status 1.
inventree-server | 2026-03-04 15:27:52,420 ERROR {'event': 'Plugin file installation failed: Collecting my_custom_plugin@ https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl==1.1.2 (from -r /home/inventree/data/plugins.txt (line 3))\n ERROR: HTTP error 404 while getting https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl==1.1.2\nERROR: Could not install requirement my_custom_plugin@ https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl==1.1.2 from https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl==1.1.2 (from -r /home/inventree/data/plugins.txt (line 3)) because of HTTP error 404 Client Error: Not Found for url: https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl==1.1.2 for URL https://my-custom-domain.com/python/my_custom_plugin/my_custom_plugin-1.1.2-py3-none-any.whl==1.1.2\n', 'ip': '172.24.0.1', 'request_id': '8096f46c-4f30-4af2-ac04-26379e699d13', 'user_id': 1, 'timestamp': '2026-03-04T15:27:52.420349Z', 'logger': 'inventree', 'level': 'error', 'exception': 'Traceback (most recent call last):\n File "/home/inventree/src/backend/InvenTree/plugin/installer.py", line 140, in install_plugins_file\n pip_command(*cmd)\n File "/home/inventree/src/backend/InvenTree/plugin/installer.py", line 38, in pip_command\n return subprocess.check_output(\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File "/usr/local/lib/python3.11/subprocess.py", line 466, in check_output\n return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File "/usr/local/lib/python3.11/subprocess.py", line 571, in run\n raise CalledProcessError(retcode, process.args,\nsubprocess.CalledProcessError: Command \'[\'/usr/local/bin/python3.11\', \'-m\', \'pip\', \'install\', \'--disable-pip-version-check\', \'-U\', \'-r\', \'/home/inventree/data/plugins.txt\']\' returned non-zero exit status 1.'}
inventree-server | 2026-03-04T15:27:52.420924Z [error ] Command '['/usr/local/bin/python3.11', '-m', 'pip', 'install', '--disable-pip-version-check', '-U', '-r', '/home/inventree/data/plugins.txt']' returned non-zero exit status 1. [inventree] ip=172.24.0.1 request_id=8096f46c-4f30-4af2-ac04-26379e699d13 user_id=1
inventree-server | 2026-03-04 15:27:52,420 ERROR {'event': CalledProcessError(1, ['/usr/local/bin/python3.11', '-m', 'pip', 'install', '--disable-pip-version-check', '-U', '-r', '/home/inventree/data/plugins.txt']), 'ip': '172.24.0.1', 'request_id': '8096f46c-4f30-4af2-ac04-26379e699d13', 'user_id': 1, 'timestamp': '2026-03-04T15:27:52.420924Z', 'logger': 'inventree', 'level': 'error'}
inventree-server | 172.24.0.1 - - [04/Mar/2026:15:27:52 +0000] "POST /api/plugins/install/ HTTP/1.1" 201 1135 "http://inventree.localhost/web/settings/admin/plugin" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36"
Steps to Reproduce
See above.
Expected behaviour
See above.
Deployment Method
Docker
Version Information
InvenTree-Version: 1.2.3
Django Version: 5.2.11
Commit Hash: 12da3b0
Commit Date: 2026-02-22
Commit Branch: null
Database: django.db.backends.postgresql
Debug-Mode: False
Deployed using Docker: True
Platform: Linux-6.8.0-52-generic-x86_64-with-glibc2.41
Installer: DOC
Active plugins: [{"name":"InvenTreeBarcode","slug":"inventreebarcode","version":"2.1.0"},{"name":"BOM Exporter","slug":"bom-exporter","version":"1.1.0"},{"name":"InvenTree Exporter","slug":"inventree-exporter","version":"1.0.0"},{"name":"Parameter Exporter","slug":"parameter-exporter","version":"2.0.0"},{"name":"InvenTreeEmailNotifications","slug":"inventree-email-notification","version":"1.0.0"},{"name":"InvenTreeUINotifications","slug":"inventree-ui-notification","version":"1.0.0"},{"name":"InvenTreeCurrencyExchange","slug":"inventreecurrencyexchange","version":"1.0.0"},{"name":"InvenTreeMachines","slug":"inventree-machines","version":"1.0.0"},{"name":"InvenTreeLabel","slug":"inventreelabel","version":"1.1.0"},{"name":"InvenTreeLabelMachine","slug":"inventreelabelmachine","version":"1.0.0"}]
Try to reproduce on the demo site
I did not try to reproduce
Is the bug reproducible on the demo site?
Not reproducible
Relevant log output
See above.