{"record":{"id":"67439779c896d63a","repo":"different-ai/openwork","slug":"den-api-public-url-cannot-contain-credentials-a-q","errorCode":null,"errorMessage":"DEN_API_PUBLIC_URL cannot contain credentials, a query string, or a fragment.","messagePattern":"DEN_API_PUBLIC_URL cannot contain credentials, a query string, or a fragment\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ee/apps/den-api/src/request-url.ts","lineNumber":104,"sourceCode":"export function normalizeConfiguredPublicApiBaseUrl(\n  value: string | undefined,\n  options: { allowInsecureHttp: boolean },\n): string | undefined {\n  const configured = value?.trim()\n  if (!configured) return undefined\n\n  let url: URL\n  try {\n    url = new URL(configured)\n  } catch {\n    throw new Error(\"DEN_API_PUBLIC_URL must be an absolute http or https URL.\")\n  }\n\n  if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n    throw new Error(\"DEN_API_PUBLIC_URL must be an absolute http or https URL.\")\n  }\n  if (url.username || url.password || url.search || url.hash) {\n    throw new Error(\"DEN_API_PUBLIC_URL cannot contain credentials, a query string, or a fragment.\")\n  }\n  if (url.protocol !== \"https:\" && !options.allowInsecureHttp && !isLocalPublicApiHost(url.hostname)) {\n    throw new Error(\"DEN_API_PUBLIC_URL must use HTTPS outside development and localhost.\")\n  }\n\n  const pathname = url.pathname.replace(/\\/+$/, \"\")\n  return `${url.origin}${pathname === \"/\" ? \"\" : pathname}`\n}\n","sourceCodeStart":86,"sourceCodeEnd":113,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-api/src/request-url.ts#L86-L113","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Strip the query string, fragment, and any user:pass@ prefix, leaving only scheme+host+optional base path.","Move credentials out of the URL into dedicated env vars/secrets if authentication is needed.","Re-test with new URL(value) and assert username/password/search/hash are all empty before deploying.","If a base path is required (e.g. /api), keep the path — only query/fragment/userinfo are rejected."],"exampleFix":"// before\nDEN_API_PUBLIC_URL=https://admin:s3cret@api.example.com/mcp?region=us#hooks\n// after\nDEN_API_PUBLIC_URL=https://api.example.com/mcp","handlingStrategy":"validation","validationCode":"const u = new URL(process.env.DEN_API_PUBLIC_URL ?? \"\")\nif (u.username || u.password || u.search || u.hash) {\n  throw new Error(\"DEN_API_PUBLIC_URL must not contain credentials, query string, or fragment\")\n}","typeGuard":"function isCleanBaseUrl(value: string | undefined): value is string {\n  try {\n    const u = new URL(value ?? \"\")\n    return (u.protocol === \"http:\" || u.protocol === \"https:\") && !u.username && !u.password && !u.search && !u.hash\n  } catch { return false }\n}","tryCatchPattern":"try {\n  const baseUrl = apiPublicUrl(env)\n} catch (e) {\n  if (e.message.includes(\"credentials, a query string, or a fragment\")) {\n    console.error(\"Strip user:pass@, ?query, and #fragment from DEN_API_PUBLIC_URL\")\n    process.exit(1)\n  }\n  throw e\n}","preventionTips":["Copy base URLs from config, never from the browser address bar","Keep credentials in dedicated secret env vars, not in URLs","Assert URL components are empty in a pre-deploy validation script","If a base path is needed, keep only the path (e.g. /api) — no query/fragment"],"tags":["configuration","env","url","validation"],"backgroundTag":"invalid-env-var","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}