decolua/9router · error · Error
Failed to decrypt Zed access token: ${message}
Error message
Failed to decrypt Zed access token: ${message} What it means
decryptZedAccessToken tries RSA privateDecrypt with OAEP-SHA256 padding first, then falls back to PKCS#1 v1.5 padding. If both decryptions fail (wrong key, wrong input encoding, corrupted ciphertext), it rethrows as "Failed to decrypt Zed access token: <underlying message>". The underlying message (from the OAEP attempt) names the real crypto failure.
Source
Thrown at open-sse/shared/zedAuth.js:154
const encrypted = Buffer.from(String(encryptedAccessToken), "base64url");
try {
return crypto
.privateDecrypt(
{ key: privateKey, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, oaepHash: "sha256" },
encrypted,
)
.toString("utf8");
} catch (oaepError) {
try {
return crypto
.privateDecrypt(
{ key: privateKey, padding: crypto.constants.RSA_PKCS1_PADDING },
encrypted,
)
.toString("utf8");
} catch {
const message = oaepError instanceof Error ? oaepError.message : String(oaepError);
throw new Error(`Failed to decrypt Zed access token: ${message}`);
}
}
}
export function buildZedUserAuthHeader(credentials) {
const psd = credentials?.providerSpecificData || {};
const userId = psd.userId || credentials?.userId;
const accessToken = credentials?.accessToken || credentials?.apiKey;
if (!userId || !accessToken) {
throw new Error("Zed credential is missing userId or accessToken");
}
return `${userId} ${accessToken}`;
}
function getSystemId(credentials) {
return String(
credentials?.providerSpecificData?.systemId || credentials?.systemId || "",
);View on GitHub (pinned to 90b52e06ff)
Solutions
- Re-run the Zed sign-in flow so userId, encrypted token, and privateKeyVerifier are regenerated together and stored as one set.
- Verify the encrypted token is pure base64url (no '=', no '%3D' escapes, no whitespace) before decrypting.
- Confirm the privateKeyVerifier belongs to the same sign-in session as the token — never mix values from different attempts.
- Read the embedded underlying message: 'bad decrypt'/length errors usually mean key/padding mismatch; base64 errors mean encoding corruption.
Example fix
// before decryptZedAccessToken(cred.tokenFromOldSession, cred.newKeyVerifier); // mismatched pair // after // store token+verifier atomically from the same sign-in decryptZedAccessToken(cred.encryptedAccessToken, cred.privateKeyVerifier);
Defensive patterns
Strategy: try-catch
Validate before calling
function isBase64Url(s) {
return typeof s === "string" && /^[A-Za-z0-9_-]+$/.test(s) && s.length % 4 !== 1;
}
// pre-check: isBase64Url(token) && verifier exists && token+verifier from same session
Type guard
const isDecryptablePair = (cred) => Boolean(cred?.encryptedAccessToken && cred?.privateKeyVerifier) && isBase64Url(cred.encryptedAccessToken);
Try / catch
let token;
try {
token = decryptZedAccessToken(encryptedAccessToken, privateKeyVerifier);
} catch (e) {
// log e.message (contains the underlying crypto reason), then re-run Zed sign-in to mint a fresh keypair+token
} Prevention
- Always store encryptedAccessToken and privateKeyVerifier atomically from the same sign-in attempt.
- Never copy credentials between machines without both parts.
- On decrypt failure, automatically trigger re-auth instead of retrying with the same data.
When it happens
Trigger: Calling decryptZedAccessToken with an encrypted token that doesn't match the stored private key verifier — mismatched keypair, non-base64url token string, truncated/garbled ciphertext, or a token encrypted with different padding/keys by a newer Zed client.
Common situations: User re-ran Zed sign-in so a NEW keypair/token pair exists while the dashboard still stores the old privateKeyVerifier; credential row copied between machines; token value URL-encoded (contains %3D) or padded with '=' instead of base64url.
Related errors
- Kiro tool input must be a JSON object
- Vertex OAuth/ADC requires a project_id. Add quota_project_id
- Vertex: failed to mint access token from Service Account JSO
- Vertex: failed to refresh access token from ADC JSON (author
- loadCodeAssist failed: HTTP ${response.status} ${errorText.s
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/7c83d0f2946f257d.
Report an issue: GitHub.