can1357/oh-my-pi · error · AIError.OAuthError

GITLAB_REDIRECT_URI loopback callbacks must use http://, got

Error message

GITLAB_REDIRECT_URI loopback callbacks must use http://, got: ${raw}

What it means

When GITLAB_REDIRECT_URI points at a loopback host (localhost, 127.0.0.1, [::1]) the local callback server is plaintext HTTP only, so HTTPS loopback URIs are rejected with this configuration OAuthError. Loopback callbacks must use http://; https:// is only accepted for non-loopback (remote) redirect URIs.

Source

Thrown at packages/ai/src/registry/oauth/gitlab-duo.ts:77

	let parsed: URL;
	try {
		parsed = new URL(raw);
	} catch {
		throw new AIError.OAuthError(`Invalid GITLAB_REDIRECT_URI: ${raw}`, {
			kind: "configuration",
			provider: "gitlab-duo",
		});
	}
	if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
		throw new AIError.OAuthError(`GITLAB_REDIRECT_URI must use http:// or https://, got: ${raw}`, {
			kind: "configuration",
			provider: "gitlab-duo",
		});
	}

	const isLoopback = parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1" || parsed.hostname === "[::1]";
	if (isLoopback && parsed.protocol !== "http:") {
		throw new AIError.OAuthError(`GITLAB_REDIRECT_URI loopback callbacks must use http://, got: ${raw}`, {
			kind: "configuration",
			provider: "gitlab-duo",
		});
	}

	const port = parsed.port ? Number.parseInt(parsed.port, 10) : parsed.protocol === "https:" ? 443 : 80;

	return {
		preferredPort: isLoopback ? port : 0,
		callbackPath: parsed.pathname || DEFAULT_CALLBACK_PATH,
		callbackHostname: isLoopback ? parsed.hostname : DEFAULT_CALLBACK_HOSTNAME,
		redirectUri: raw,
	};
}

function mapTokenResponse(payload: {
	access_token?: string;
	refresh_token?: string;

View on GitHub (pinned to 9690622007)

Solutions

  1. Change the scheme of GITLAB_REDIRECT_URI from https:// to http:// for loopback hosts, e.g. http://localhost:8080/callback.
  2. Update the redirect URI registered on your GitLab OAuth application to the same http:// loopback value (GitLab does not require TLS for loopback).
  3. If you genuinely need HTTPS, use a non-loopback hostname (a real domain with TLS termination).
  4. Unset GITLAB_REDIRECT_URI to use the default http://localhost:8080/callback flow.

Example fix

// before (.env)
GITLAB_REDIRECT_URI=https://localhost:8080/callback

// after (.env)
GITLAB_REDIRECT_URI=http://localhost:8080/callback
Defensive patterns

Strategy: validation

Validate before calling

const raw = process.env.GITLAB_REDIRECT_URI?.trim();
if (raw) {
  const u = new URL(raw);
  const loopback = ["localhost", "127.0.0.1", "[::1]"].includes(u.hostname);
  if (loopback && u.protocol !== "http:") {
    throw new Error(`loopback GITLAB_REDIRECT_URI must be http://, got: ${raw}`);
  }
}

Try / catch

try {
  await loginGitLabDuo(callbacks);
} catch (err) {
  if (err?.kind === "configuration" && String(err.message).includes("loopback callbacks must use http://")) {
    process.env.GITLAB_REDIRECT_URI = process.env.GITLAB_REDIRECT_URI!.replace("https://", "http://");
    await loginGitLabDuo(callbacks);
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: GITLAB_REDIRECT_URI like 'https://localhost:8080/callback', 'https://127.0.0.1/callback', or 'https://[::1]:9090/callback' — a URL that parses, uses an allowed scheme, but combines a loopback hostname with https:.

Common situations: Developers assuming OAuth redirect URIs must be HTTPS everywhere and registering 'https://localhost/...' on their GitLab app; copying examples from web-app OAuth setups; IDE auto-completion suggesting https for localhost.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/d548ab9862a97669. Report an issue: GitHub.