can1357/oh-my-pi · error · Error
HTTPS loopback redirect URIs require oauth.callbackPort to p
Error message
HTTPS loopback redirect URIs require oauth.callbackPort to point at the local HTTP callback listener behind your TLS terminator
What it means
validateRedirectConfig handles the case where the redirect URI is an HTTPS loopback URL. The library's local callback listener speaks plain HTTP, so with an https redirect URI you must terminate TLS separately (reverse proxy/TLS terminator) and run the local listener on a different port, which must be declared via oauth.callbackPort. If callbackPort is missing, the library cannot know where to bind the HTTP listener and throws.
Source
Thrown at packages/coding-agent/src/mcp/oauth-flow.ts:164
}
function parseRedirectUri(redirectUri: string | undefined): URL | undefined {
return redirectUri ? new URL(redirectUri) : undefined;
}
function getUriPort(uri: URL): number {
if (uri.port !== "") return Number(uri.port);
return uri.protocol === "https:" ? 443 : 80;
}
function validateRedirectConfig(config: MCPOAuthConfig, redirectUri: string | undefined): void {
const parsed = parseRedirectUri(redirectUri);
if (parsed?.protocol !== "https:" || !isLoopbackHostname(parsed.hostname)) {
return;
}
if (config.callbackPort === undefined) {
throw new Error(
"HTTPS loopback redirect URIs require oauth.callbackPort to point at the local HTTP callback listener behind your TLS terminator",
);
}
if (config.callbackPort === getUriPort(parsed)) {
throw new Error(
"HTTPS loopback redirect URIs cannot reuse the same local port; terminate TLS separately and forward to oauth.callbackPort",
);
}
}
function resolveCallbackPort(callbackPort: number | undefined, redirectUri: string | undefined): number {
if (callbackPort !== undefined) return callbackPort;
const parsed = parseRedirectUri(redirectUri);
if (parsed?.protocol !== "http:" || !isLoopbackHostname(parsed.hostname)) {
return DEFAULT_PORT;
}View on GitHub (pinned to 9690622007)
Solutions
- Set oauth.callbackPort to the port your local HTTP callback listener should bind, distinct from the HTTPS port in the redirect URI
- Configure your TLS terminator to forward from the https redirect port to the callbackPort
- Alternatively, switch the redirect URI to plain http://localhost:<port> if your provider allows insecure loopback redirects
Example fix
// before
"oauth": { "redirectUri": "https://localhost:8443/auth/callback" }
// after: local HTTP listener on 1455, TLS terminator forwards 8443 -> 1455
"oauth": { "redirectUri": "https://localhost:8443/auth/callback", "callbackPort": 1455 } Defensive patterns
Strategy: validation
Validate before calling
const uri = config.oauth?.redirectUri;
if (uri) {
const p = new URL(uri);
const loopback = ['localhost', '127.0.0.1', '[::1]'].includes(p.hostname);
if (p.protocol === 'https:' && loopback && config.oauth.callbackPort === undefined) {
throw new Error('https loopback redirectUri requires oauth.callbackPort for the local HTTP listener');
}
} Try / catch
try {
startOAuthFlow(config);
} catch (e) {
if (e.message.includes('HTTPS loopback redirect URIs require oauth.callbackPort')) {
throw new Error('Add oauth.callbackPort (a plain-HTTP port behind your TLS terminator) to your MCP oauth config');
} else throw e;
} Prevention
- If you don't run a TLS terminator locally, use plain http://localhost:<port> redirect URIs
- When using https loopback redirects, always pair them with a distinct oauth.callbackPort
- Document the terminator topology (https port -> callbackPort) in your config comments
- Test the OAuth flow after any redirect/terminator config change
When it happens
Trigger: Configuring an https:// loopback redirect URI (e.g. https://localhost:8443/callback) in oauth.redirectUri while leaving oauth.callbackPort undefined, then resolving callback options via resolveCallbackOptions.
Common situations: Users behind a local TLS terminator (caddy, nginx) who registered an https loopback redirect with their provider but forgot to tell the library which plain-HTTP port the local listener should use; assuming the library can serve HTTPS itself.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- GITLAB_REDIRECT_URI loopback callbacks must use http://, got
- HTTPS loopback redirect URIs cannot reuse the same local por
- Unknown OAuth provider: ${provider}
- OAuth provider "${provider}" does not support token refresh
- ${name} path does not exist: ${trimmed}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/eb8bf9a2c967cb5a.
Report an issue: GitHub.