decolua/9router · error · Error
Invalid callback URL format
Error message
Invalid callback URL format
What it means
handleManualSubmit in KiroSocialOAuthModal parses the manually pasted callback URL with `new URL(callbackUrl)`; when the string is not a valid absolute URL the constructor throws and this wrapper converts it into a readable Error. The modal accepts either `kiro://...` or `http://localhost...` callback shapes, both of which must still be parseable by the URL constructor (kiro:// works because it has scheme + rest).
Source
Thrown at src/shared/components/KiroSocialOAuthModal.js:70
setError(err.message);
setStep("error");
}
};
initAuth();
}, [isOpen, provider]);
const handleManualSubmit = async () => {
try {
setError(null);
// Parse callback URL - can be either kiro:// or http://localhost format
let url;
try {
url = new URL(callbackUrl);
} catch (e) {
// If URL parsing fails, might be malformed
throw new Error("Invalid callback URL format");
}
const code = url.searchParams.get("code");
const state = url.searchParams.get("state");
const errorParam = url.searchParams.get("error");
if (errorParam) {
throw new Error(url.searchParams.get("error_description") || errorParam);
}
if (!code) {
throw new Error("No authorization code found in URL");
}
// Exchange code for tokens
const res = await fetch("/api/oauth/kiro/social-exchange", {
method: "POST",
headers: { "Content-Type": "application/json" },View on GitHub (pinned to 90b52e06ff)
Solutions
- Re-copy the entire callback URL, including the scheme (kiro:// or http://), and paste it again.
- Trim whitespace: paste after `.trim()`-ing the input, or check the raw string in devtools.
- If your deep link doesn't include a scheme, prepend one manually (e.g. kiro://callback?code=...&state=...).
- Verify the URL contains `code` and `state` query params — if you only got the code, this error may appear first for malformed input.
Example fix
// before
let url;
try {
url = new URL(callbackUrl);
} catch (e) {
throw new Error("Invalid callback URL format");
}
// after
let url;
try {
url = new URL(callbackUrl.trim());
} catch (e) {
throw new Error(`Invalid callback URL format: "${callbackUrl.slice(0, 80)}" (expected kiro://... or http://localhost/...?code=...)`);
} Defensive patterns
Strategy: validation
Validate before calling
function isValidCallbackUrl(s) {
if (typeof s !== "string") return false;
try {
const u = new URL(s.trim());
return u.protocol === "kiro:" || (u.protocol === "http:" || u.protocol === "https:");
} catch {
return false;
}
}
// call before handleManualSubmit
if (!isValidCallbackUrl(callbackUrl)) {
setError("Paste the full callback URL (kiro://... or http://localhost/...?code=...)");
return;
} Type guard
function asParsedUrl(value) {
try { const u = new URL(String(value).trim()); return /^kiro:|^https?:$/.test(u.protocol) ? u : null; }
catch { return null; }
} Try / catch
try {
const url = asParsedUrl(callbackUrl);
if (!url) throw new Error(`Invalid callback URL format: "${String(callbackUrl).slice(0, 80)}"`);
// proceed
} catch (err) {
setError(err.message);
} Prevention
- Copy the complete redirected URL including scheme and query string.
- Trim whitespace/newlines before parsing.
- Prefer deep-link capture over manual paste where possible.
- Show a placeholder in the input showing the expected format.
When it happens
Trigger: User pastes something into the manual callback input that `new URL()` cannot parse: an empty string, a bare authorization code, a URL missing its scheme (e.g. "localhost:PORT/callback?code=..." is actually misparsed), truncated copy/paste, or text with stray whitespace/newlines.
Common situations: Copying only part of the callback URL from the browser address bar; pasting the code alone instead of the full URL; the kiro:// deep link got mangled by the terminal or chat client; leading/trailing whitespace from copying.
Related errors
- API key is required
- API key validation failed: ${error.message}
- No authorization code found in URL
- Missing Zed callback URL
- Invalid Zed callback URL
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/b02559e249429272.
Report an issue: GitHub.