different-ai/openwork · error

DEN_API_PUBLIC_URL cannot contain credentials, a query strin

Error message

DEN_API_PUBLIC_URL cannot contain credentials, a query string, or a fragment.

What it means

This error is thrown when DEN_API_PUBLIC_URL parses as an absolute http/https URL but also embeds userinfo (username/password), a query string, or a fragment. Such components make the value unsuitable as a clean base URL used to construct public API links, so normalizeConfiguredPublicApiBaseUrl rejects it.

Source

Thrown at ee/apps/den-api/src/request-url.ts:104

export function normalizeConfiguredPublicApiBaseUrl(
  value: string | undefined,
  options: { allowInsecureHttp: boolean },
): string | undefined {
  const configured = value?.trim()
  if (!configured) return undefined

  let url: URL
  try {
    url = new URL(configured)
  } catch {
    throw new Error("DEN_API_PUBLIC_URL must be an absolute http or https URL.")
  }

  if (url.protocol !== "http:" && url.protocol !== "https:") {
    throw new Error("DEN_API_PUBLIC_URL must be an absolute http or https URL.")
  }
  if (url.username || url.password || url.search || url.hash) {
    throw new Error("DEN_API_PUBLIC_URL cannot contain credentials, a query string, or a fragment.")
  }
  if (url.protocol !== "https:" && !options.allowInsecureHttp && !isLocalPublicApiHost(url.hostname)) {
    throw new Error("DEN_API_PUBLIC_URL must use HTTPS outside development and localhost.")
  }

  const pathname = url.pathname.replace(/\/+$/, "")
  return `${url.origin}${pathname === "/" ? "" : pathname}`
}

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Strip the query string, fragment, and any user:pass@ prefix, leaving only scheme+host+optional base path.
  2. Move credentials out of the URL into dedicated env vars/secrets if authentication is needed.
  3. Re-test with new URL(value) and assert username/password/search/hash are all empty before deploying.
  4. If a base path is required (e.g. /api), keep the path — only query/fragment/userinfo are rejected.

Example fix

// before
DEN_API_PUBLIC_URL=https://admin:s3cret@api.example.com/mcp?region=us#hooks
// after
DEN_API_PUBLIC_URL=https://api.example.com/mcp
Defensive patterns

Strategy: validation

Validate before calling

const u = new URL(process.env.DEN_API_PUBLIC_URL ?? "")
if (u.username || u.password || u.search || u.hash) {
  throw new Error("DEN_API_PUBLIC_URL must not contain credentials, query string, or fragment")
}

Type guard

function isCleanBaseUrl(value: string | undefined): value is string {
  try {
    const u = new URL(value ?? "")
    return (u.protocol === "http:" || u.protocol === "https:") && !u.username && !u.password && !u.search && !u.hash
  } catch { return false }
}

Try / catch

try {
  const baseUrl = apiPublicUrl(env)
} catch (e) {
  if (e.message.includes("credentials, a query string, or a fragment")) {
    console.error("Strip user:pass@, ?query, and #fragment from DEN_API_PUBLIC_URL")
    process.exit(1)
  }
  throw e
}

Prevention

When it happens

Trigger: DEN_API_PUBLIC_URL values like "https://user:pass@api.example.com", "https://api.example.com/?env=prod", or "https://api.example.com/#main" — any non-empty url.username, url.password, url.search, or url.hash.

Common situations: Pasting a full URL copied from a browser address bar including #section or ?token=...; embedding basic-auth credentials in the URL instead of a secret; template tooling appending query parameters for tracking.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/67439779c896d63a. Report an issue: GitHub.