You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Web and desktop clients cannot authenticate with Unicode server credentials #46224
The web and desktop clients pass username:password directly to btoa() when creating a Basic-auth token. btoa() accepts only binary strings, so credentials containing characters outside the one-byte range throw InvalidCharacterError. Characters such as ä do not throw, but are encoded as a single byte instead of UTF-8, so the server decodes a different password and rejects authentication.
This affects server health checks, protocol detection, API clients, and legacy terminal authentication because they share the same credential encoder. The server already generates and decodes Basic-auth credentials as UTF-8. The app should convert the credential string to UTF-8 bytes before applying standard Base64 encoding.
Plugins
N/A
OpenCode version
N/A (reproduced in the shared client authentication helper)
Steps to reproduce
Start an OpenCode server with OPENCODE_SERVER_PASSWORD='秘密🔐'.
Open the web or desktop client and add that server.
Enter the same password and attempt to connect.
Observe that encoding throws InvalidCharacterError and the connection cannot be established.
A second case is päss: encoding does not throw, but the server receives invalid UTF-8 and authentication fails.
Expected behavior: Unicode usernames and passwords should be encoded as UTF-8 bytes before Base64 encoding and should authenticate successfully.
Screenshot and/or share link
Not provided; the credential helper provides a deterministic reproduction.
Thanks for the clear report. I reproduced this on v2.2.0, the latest release, since no version was given. It still happens on the latest dev (06d3c060).
I started opencode serve with OPENCODE_SERVER_PASSWORD set to päss, 秘密🔐 and secret. Then I called /api/info with a token from the app's encoder (btoa("opencode:" + password)) and with a UTF-8 token:
päss: the app's token gets 401; the UTF-8 token gets 200.
秘密🔐: the app's encoder throws InvalidCharacterError: The string contains invalid characters.; the UTF-8 token gets 200.
secret: both get 200.
The server expects UTF-8 credentials, so the client-side encoder in packages/app/src/runtime/server/api.ts (authTokenFromCredentials) is the mismatch. The script below reproduces it. Until it's fixed, an ASCII-only server password avoids the problem.
Reproduction script (repro.sh)
#!/usr/bin/env bash# Reproduces anomalyco/opencode#46224: the web/desktop app's Basic-auth encoder# (authTokenFromCredentials in packages/app/src/runtime/server/api.ts) uses btoa()# directly, so Unicode server passwords either throw or are sent as Latin-1.# Usage: OPENCODE="opencode" ./repro.sh (defaults to `opencode` on PATH)set -u
OPENCODE=${OPENCODE:-opencode}
WORK=$(mktemp -d)cd"$WORK"start() { # port password# separate data dirs so the three servers don't race on the same database
mkdir -p "$WORK/h$1"
XDG_DATA_HOME="$WORK/h$1/data" XDG_STATE_HOME="$WORK/h$1/state" XDG_CONFIG_HOME="$WORK/h$1/config" XDG_CACHE_HOME="$WORK/h$1/cache" \
OPENCODE_SERVER_PASSWORD="$2"$OPENCODE serve --hostname 127.0.0.1 --port "$1">"$WORK/s$1.log"2>&1&echo$!
}
P1=$(start 47101 'päss')
P2=$(start 47102 '秘密🔐')
P3=$(start 47103 'secret')trap'kill $P1 $P2 $P3 2>/dev/null' EXIT
forpin 47101 47102 47103;doforiin$(seq 60);do curl -s -o /dev/null "http://127.0.0.1:$p/"&&break; sleep 0.5;donedone
cat >"$WORK/check.ts"<<'EOF'// Same encoder as the app's authTokenFromCredentials (v2.2.0 and dev)const appToken = (password: string) => btoa(`opencode:${password}`)const utf8Token = (password: string) => Buffer.from(`opencode:${password}`, "utf8").toString("base64")async function probe(port: number, password: string) { const url = `http://127.0.0.1:${port}/api/info` let app: string try { const r = await fetch(url, { headers: { authorization: `Basic ${appToken(password)}` } }) app = `HTTP ${r.status}` } catch (e: any) { app = `throws ${e?.name}: ${e?.message}` } const u = await fetch(url, { headers: { authorization: `Basic ${utf8Token(password)}` } }) console.log(`password ${JSON.stringify(password)}: app encoder -> ${app}; UTF-8 encoder -> HTTP ${u.status}`)}await probe(47101, "päss")await probe(47102, "秘密🔐")await probe(47103, "secret")EOF
bun "$WORK/check.ts"
Activity
sdivyanshu90 commentedon Sep 19, 2026
Could you please review this issue?
opencodejr commentedon Oct 28, 2026
Thanks for the clear report. I reproduced this on v2.2.0, the latest release, since no version was given. It still happens on the latest
dev(06d3c060).I started
opencode servewithOPENCODE_SERVER_PASSWORDset topäss,秘密🔐andsecret. Then I called/api/infowith a token from the app's encoder (btoa("opencode:" + password)) and with a UTF-8 token:päss: the app's token gets 401; the UTF-8 token gets 200.秘密🔐: the app's encoder throwsInvalidCharacterError: The string contains invalid characters.; the UTF-8 token gets 200.secret: both get 200.The server expects UTF-8 credentials, so the client-side encoder in
packages/app/src/runtime/server/api.ts(authTokenFromCredentials) is the mismatch. The script below reproduces it. Until it's fixed, an ASCII-only server password avoids the problem.Reproduction script (repro.sh)
Run it:
bash repro.sh