{"record":{"id":"b14bf5025a845c31","repo":"hcengineering/platform","slug":"please-provide-front-url","errorCode":null,"errorMessage":"Please provide front url","messagePattern":"Please provide front url","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/account/src/utils.ts","lineNumber":1448,"sourceCode":"  return await db.socialId.findOne({ type: SocialIdType.EMAIL, value: email })\n}\n\nexport function getMailUrl (): { mailURL: string, mailAuth: string | undefined } {\n  const mailURL = getMetadata(accountPlugin.metadata.MAIL_URL)\n\n  if (mailURL === undefined || mailURL === '') {\n    throw new Error('Please provide email service url')\n  }\n  const mailAuth = getMetadata(accountPlugin.metadata.MAIL_AUTH_TOKEN)\n\n  return { mailURL, mailAuth }\n}\n\nexport function getFrontUrl (branding: Branding | null): string {\n  const front = branding?.front ?? getMetadata(accountPlugin.metadata.FrontURL)\n\n  if (front === undefined || front === '') {\n    throw new Error('Please provide front url')\n  }\n\n  return front\n}\n\nexport async function updateArchiveInfo (\n  ctx: MeasureContext,\n  db: AccountDB,\n  workspace: WorkspaceUuid,\n  value: boolean\n): Promise<void> {\n  const workspaceInfo = await getWorkspaceById(db, workspace)\n  if (workspaceInfo === null) {\n    throw new PlatformError(new Status(Severity.ERROR, platform.status.WorkspaceNotFound, { workspaceUuid: workspace }))\n  }\n\n  await db.workspaceStatus.update(\n    { workspaceUuid: workspace },","sourceCodeStart":1430,"sourceCodeEnd":1466,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/server/account/src/utils.ts#L1430-L1466","documentation":"getFrontUrl resolves the frontend base URL from branding.front, falling back to the FrontURL metadata, and throws Error('Please provide front url') when neither is set. Links in emails (confirmations, invites) need this base URL to be constructed.","triggerScenarios":"Calling getFrontUrl(branding) when branding is null or branding.front is undefined AND metadata accountPlugin.metadata.FrontURL is missing or empty.","commonSituations":"Self-hosted deployments without FrontURL configured; branding object passed without a front field; migrating instances where the front URL was dropped from config.","solutions":["Set the FrontURL metadata (env/config) for the account service and restart.","Ensure the branding record includes a non-empty front field, or pass null branding so the fallback applies.","Check that neither config layer overrides FrontURL to an empty string.","Add a deployment smoke test that resolves getFrontUrl after startup."],"exampleFix":"// config\n// before\n# FrontURL not set\n// after\nFrontURL=https://app.example.com","handlingStrategy":"validation","validationCode":"if (!branding?.front && !process.env.FRONT_URL) {\n  throw new Error('Either branding.front or FrontURL metadata must be set')\n}","typeGuard":"function hasFrontUrl(branding: Branding | null): boolean {\n  return Boolean(branding?.front) || Boolean(getMetadata(accountPlugin.metadata.FrontURL))\n}","tryCatchPattern":"try {\n  const front = getFrontUrl(branding)\n} catch (err) {\n  if (err instanceof Error && err.message.includes('front url')) {\n    // configure FrontURL or pass branding with a front field\n  } else throw err\n}","preventionTips":["Always provision FrontURL in account service config.","When passing branding, ensure the front field is populated.","Include front URL in post-deploy smoke tests.","Never override FrontURL with an empty string in environment-specific configs."],"tags":["configuration","branding","missing-env-var"],"backgroundTag":"missing-env-var","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}