decolua/9router · error · Error

Invalid Zed callback URL

Error message

Invalid Zed callback URL

What it means

parseZedCallbackPayload tries to interpret the pasted Zed sign-in callback as JSON, then as an absolute URL, then as a bare query string (`?a=b`). If the input is not valid JSON and none of the URL constructions parse, it throws "Invalid Zed callback URL". This guards against users pasting truncated or malformed OAuth callback data when linking a Zed account.

Source

Thrown at open-sse/shared/zedAuth.js:117

}

/** Parse the pasted native-app callback URL/JSON/query into userId + encrypted token. */
export function parseZedCallbackPayload(input) {
  const raw = String(input || "").trim();
  if (!raw) throw new Error("Missing Zed callback URL");

  let data = {};
  try {
    data = JSON.parse(raw);
  } catch {
    let url;
    try {
      url = new URL(raw);
    } catch {
      try {
        url = new URL(`http://127.0.0.1/?${raw.replace(/^\?/, "")}`);
      } catch {
        throw new Error("Invalid Zed callback URL");
      }
    }
    url.searchParams.forEach((value, key) => {
      data[key] = value;
    });
  }

  const userId = data.user_id || data.userId;
  const encryptedAccessToken = data.access_token || data.accessToken || data.token;
  if (!userId || !encryptedAccessToken) {
    throw new Error("Zed callback must include user_id and access_token");
  }
  return { userId: String(userId), encryptedAccessToken: String(encryptedAccessToken) };
}

/** Decrypt the RSA-encrypted access token using the stored private key. */
export function decryptZedAccessToken(encryptedAccessToken, privateKeyVerifier) {
  const privateKey = decodeZedPrivateKeyVerifier(privateKeyVerifier);

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Re-do the Zed sign-in flow and paste the FULL callback URL exactly as captured (including http://127.0.0.1:PORT/... and query string).
  2. If you have raw params only, format them as a query string like `user_id=123&access_token=...` — the parser accepts a bare `?a=b` fragment.
  3. Alternatively pass a JSON object string containing user_id and access_token keys.
  4. Trim whitespace/newlines from the pasted value before calling; the function trims but inner invalid characters still break URL parsing.

Example fix

// before
parseZedCallbackPayload("user_id=42 access_token=abc"); // space instead of &
// after
parseZedCallbackPayload("user_id=42&access_token=abc");
Defensive patterns

Strategy: validation

Validate before calling

function isValidZedCallbackInput(input) {
  const raw = String(input || "").trim();
  if (!raw) return false;
  try { JSON.parse(raw); return true; } catch {}
  try { new URL(raw); return true; } catch {}
  try { new URL(`http://127.0.0.1/?${raw.replace(/^\?/, "")}`); return true; } catch {}
  return false;
}
// call before: if (!isValidZedCallbackInput(pasted)) prompt user to re-copy;

Type guard

const isNonEmptyString = (v) => typeof v === "string" && v.trim().length > 0;

Try / catch

try {
  const { userId, encryptedAccessToken } = parseZedCallbackPayload(input);
} catch (e) {
  if (e.message === "Invalid Zed callback URL") {
    // re-prompt user to paste the complete callback URL
  } else throw e;
}

Prevention

When it happens

Trigger: Calling parseZedCallbackPayload with a string that is neither valid JSON, a parseable URL, nor a bare query string — e.g. pasting only part of the callback URL, an HTML error page, or free text.

Common situations: User copies the callback URL but truncates it (missing scheme or query), pastes the sign-in page URL instead of the redirect, or the clipboard grabbed extra characters. Also happens when automation feeds the wrong payload (e.g. a state code only).

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/aa9a26b69613e290. Report an issue: GitHub.