So I completely removed my Ubuntu container and then installed a new one so I'd have a Base Ubuntu running. Then I did the main curl install for Sparkbox and logged in with my bootstrap token, plus set the password. At this point, I should have influenced nothing but the Sparkbox password. I open Portainer from the home page, copy the admin password, then paste it over type admin for the user name, and i get Failure Unauthorized This is the output from Chrome's Developer Network Console i18n.ts:10 GET http://192.168.1.170:9000/locales/en-US/translation.json 404 (Not Found) setTimeout (anonymous) @ i18n.ts:10 webpackrequire @ bootstrap:19 (anonymous) @ main.76cf29d….js:2 (anonymous) @ chunk loaded:25 (anonymous) @ main.76cf29d….js:2 (anonymous) @ jsonp chunk loading:73 (anonymous) @ main.76cf29d….js:2 i18n.ts:10 i18next::backendConnector: loading namespace translation for language en-US failed failed loading /locales/en-US/translation.json; status code: 404 setTimeout (anonymous) @ i18n.ts:10 webpackrequire @ bootstrap:19 (anonymous) @ main.76cf29d….js:2 (anonymous) @ chunk loaded:25 (anonymous) @ main.76cf29d….js:2 (anonymous) @ jsonp chunk loading:73 (anonymous) @ main.76cf29d….js:2 i18next.js:27 i18next::backendConnector: loaded namespace translation for language en {reactExample: {…}, users: {…}} i18next.js:27 i18next: languageChanged en-US i18next.js:27 i18next: initialized {debug: true, initImmediate: true, ns: Array(1), defaultNS: Array(1), fallbackLng: Array(1), …} useLoadCurrentUser.ts:23 GET http://192.168.1.170:9000/api/users/me 401 (Unauthorized) Promise.then (anonymous) @ useLoadCurrentUser.ts:23 tryCatch @ useLoadCurrentUser.ts:2 (anonymous) @ useLoadCurrentUser.ts:2 (anonymous) @ useLoadCurrentUser.ts:2 asyncGeneratorStep @ useLoadCurrentUser.ts:2 next @ useLoadCurrentUser.ts:2 (anonymous) @ useLoadCurrentUser.ts:2 (anonymous) @ useLoadCurrentUser.ts:2 (anonymous) @ useLoadCurrentUser.ts:28 getCurrentUser @ useLoadCurrentUser.ts:22 loadUserData @ authentication.js:106 initAsync @ authentication.js:46 await in initAsync (anonymous) @ async.js:14 (anonymous) @ async.js:20 init @ authentication.js:72 (anonymous) @ module.js:28 (anonymous) @ module.js:59 (anonymous) @ async.js:14 (anonymous) @ async.js:20 (anonymous) @ module.js:53 setTimeout webpackrequire @ bootstrap:19 10616 @ vendor.086668e….js:2 webpackrequire @ bootstrap:19 webpackrequire @ bootstrap:19 83082 @ main.76cf29d….js:2 webpackrequire @ bootstrap:19 (anonymous) @ main.76cf29d….js:2 (anonymous) @ chunk loaded:25 (anonymous) @ main.76cf29d….js:2 (anonymous) @ jsonp chunk loading:73 (anonymous) @ main.76cf29d….js:2 injection-topics.js:1 Browsing Topics API not found, nothing to remove on http://192.168.1.170:9000/!/auth, main frame :9000/!/auth:1 Form submission canceled because the form is not connected angular.js:13692 POST http://192.168.1.170:9000/api/auth 422 (Unprocessable Entity) (anonymous) @ angular.js:13692 (anonymous) @ angular.js:13418 (anonymous) @ angular.js:13159 (anonymous) @ angular.js:18075 (anonymous) @ angular.js:18123 $digest @ angular.js:19241 $apply @ angular.js:19630 (anonymous) @ angular.js:29127 dispatch @ jquery.js:5430 (anonymous) @ jquery.js:5234
7 replies
tomspark wrote:
Actual root cause found and v1.6.101 is now live. Portainer 2.41 silently changed --admin-password-file semantics to expect plaintext (it hashes internally now), not the bcrypt hash SparkBox has been writing since v1.0. Your 422 was Portainer storing our bcrypt-string AS the plaintext password — bcrypt(bcrypthash) ≠ user's actual plaintext. To apply: sudo sparkbox update sudo sparkbox repair-portainer Login will work this time. Your browser-network 422 evidence was a huge help getting this onto the class-level row early — thanks for the detailed debugging.
tomspark wrote:
This is a known class-level bug — sparkboxfan 8799 hit the same Portainer-422 on 2026-05-09 and v1.6.82's self-heal didn't fully close it for fresh installs. Manual fix that always works (uses Portainer's own first-run wizard, you set the password): sudo docker stop sb-portainer sudo rm -rf /opt/sparkbox/modules/core/config/portainer/ sudo docker start sb-portainer Then reload http://192.168.1.170:9000 — Portainer's wizard will show up, set your own password (it requires 12+ chars). For the v1.6.99 fix on my end: I suspect SparkBox is generating a password shorter than Portainer's 12-char minimum, which is exactly what produces that 422 response. Run wc -c < /opt/sparkbox/state/portainer-admin-password.txt and paste the number. If it's < 13 (12 chars + newline), that's the bug confirmed and I can ship a patch that closes it for everyone.
tomspark wrote:
Update — your fresh-install 422 is now confirmed class-level (3 reports across 3 unrelated installs) and v1.6.99 ships a rescue command for it: sudo sparkbox update sudo sparkbox repair-portainer Wipes Portainer's bolt DB, regenerates plaintext + bcrypt hash via the same fallback chain install.sh uses, restarts the container, then verifies the new login works via curl POST /api/auth before exiting. New password lands in state/portainer-admin-password.txt. sparkbox doctor also got a [Portainer Auth] probe so future installs that hit this will get auto-diagnosed with a direct pointer to repair-portainer instead of users having to guess. Root-cause auto-heal in install.sh is deferred to v1.7.x — appreciated the diagnostic on this one, that's what got it onto the class-level row.
GamerX06 wrote:
I am just getting home from work and boy am I thrilled that my posts were helpful!!! I'd just like to say that I really appreciate your entire demeanor and outlook on things; it is rather refreshing! I am going to run the commands you posted and report back on my results in just a few minutes
GamerX06 wrote:
SUCCESS!!! I was able to log into Portainer with the generated creds! The speed at which you are getting these bugs dealt with is so cool to see in real time. I refresh tomsparkbox.com/changelog whenever I get on my PC and every few hours. I plan on helping as much as I can. Thanks to you, I am quickly getting more familiar with Linux CLI
tomspark wrote:
That's the third independent confirm on v1.6.101 — really appreciate you sticking through the 3-version chase to land it. Your browser-network 422 evidence + LaggyGamerZA's manual bcrypt-check were what proved it was a Portainer 2.41 contract change, not our hash generation. Class-level bug officially closed. Thanks for the changelog watching — that's the loop working exactly as designed. If you hit anything else on this fresh install, drop a thread.
tomspark wrote:
Welcome back. Qbit routes through gluetun, so first check is whether the VPN's healthy. SSH in: docker logs sb-gluetun --tail 30 Look for any 'connection dropped', 'reconnecting', or repeated public ip lines. If gluetun's churning or stuck, qbit shows peers but downloads nothing — same shape as the downstream issues we hit yesterday. Paste those last 30 lines and we'll go from there.