{"record":{"id":"2ce69b1627065e25","repo":"mastra-ai/mastra","slug":"mastraauthworkos-could-not-resolve-a-callback-url","errorCode":null,"errorMessage":"MastraAuthWorkos could not resolve a callback URL: pass `redirectUri` (WORKOS_REDIRECT_URI) or configure the host `publicUrl`.","messagePattern":"MastraAuthWorkos could not resolve a callback URL: pass `redirectUri` \\(WORKOS_REDIRECT_URI\\) or configure the host `publicUrl`\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"auth/workos/src/auth-provider.ts","lineNumber":786,"sourceCode":"  /**\n   * One-time host initialization. Resolves the redirect URI from the host's\n   * `publicUrl` (`<publicUrl>/auth/callback`) when it was not provided in the\n   * options or via `WORKOS_REDIRECT_URI`.\n   *\n   * Fails at prepare time rather than handing WorkOS an empty redirect URI on\n   * the first login (which breaks hosted login with an opaque provider error).\n   */\n  async init(ctx: AuthInitContext): Promise<void> {\n    if (!this.redirectUri && ctx.publicUrl) {\n      this.redirectUri = `${ctx.publicUrl}/auth/callback`;\n      this.config.redirectUri = this.redirectUri;\n      // Rebuild the session storage/auth service so they observe the resolved\n      // redirect URI rather than the empty placeholder from construction.\n      const storage = new WebSessionStorage(this.config);\n      this.authService = new AuthService(this.config, storage, this.workos as any, sessionEncryption);\n    }\n    if (!this.redirectUri) {\n      throw new Error(\n        'MastraAuthWorkos could not resolve a callback URL: pass `redirectUri` (WORKOS_REDIRECT_URI) or configure the host `publicUrl`.',\n      );\n    }\n  }\n\n  // ============================================================================\n  // IOrganizationsProvider Implementation\n  // ============================================================================\n\n  /**\n   * Ensure the user belongs to a WorkOS organization, creating a personal org\n   * on first use when they have none.\n   *\n   * - ≥1 membership → return the first org id (they already belong somewhere;\n   *   we never auto-create when a membership exists).\n   * - 0 memberships → create a personal org + membership and return its id.\n   *\n   * Idempotency: the create call carries `externalId = userId` and a stable","sourceCodeStart":768,"sourceCodeEnd":804,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/auth/workos/src/auth-provider.ts#L768-L804","documentation":"MastraAuthWorkos defers redirect-URI resolution until late in setup (it may rebuild session storage and the auth service once the URI is resolved from the host's publicUrl). After that resolution step, if this.redirectUri is still empty, no OAuth callback can be constructed, so it throws with a message pointing at both configuration paths.","triggerScenarios":"Constructing MastraAuthWorkos without options.redirectUri, without WORKOS_REDIRECT_URI, and on a host that has no publicUrl configured — the final guard in setup detects this.redirectUri is still falsy and throws.","commonSituations":"Local/embedded deployments where no publicUrl is set; monorepo server started without server config; migration where redirectUri config moved but env var never added; runtime host (Mastra server) not propagating publicUrl into the auth provider.","solutions":["Set WORKOS_REDIRECT_URI to your full callback URL","Configure the server host publicUrl (e.g. server: { publicUrl: 'https://app.example.com' } in Mastra config) so the callback can be derived","Pass redirectUri in the provider options: new MastraAuthWorkos({ ..., redirectUri: '...' })","Verify with a log/config dump that the host publicUrl actually reaches init() before this guard runs"],"exampleFix":"// before\nnew MastraAuthWorkos({ apiKey, clientId });\n// after\nnew MastraAuthWorkos({ apiKey, clientId, redirectUri: 'https://app.example.com/auth/callback' });","handlingStrategy":"validation","validationCode":"function assertCallbackResolvable(opts, serverConfig) {\n  const redirectUri = opts?.redirectUri ?? process.env.WORKOS_REDIRECT_URI;\n  const publicUrl = serverConfig?.publicUrl;\n  if (!redirectUri && !publicUrl) {\n    throw new Error('MastraAuthWorkos needs WORKOS_REDIRECT_URI or server publicUrl to derive its callback URL');\n  }\n  return redirectUri ?? new URL('/auth/callback', publicUrl).toString();\n}","typeGuard":"function hasResolvableCallback(opts, serverConfig) {\n  return Boolean((opts?.redirectUri ?? process.env.WORKOS_REDIRECT_URI) || serverConfig?.publicUrl);\n}","tryCatchPattern":"try {\n  auth = new MastraAuthWorkos(options);\n} catch (e) {\n  if (e.message.includes('could not resolve a callback URL')) {\n    throw new ConfigError('Set WORKOS_REDIRECT_URI or server.publicUrl so the OAuth callback can be built');\n  }\n  throw e;\n}","preventionTips":["Configure server.publicUrl in every deployed environment (including staging)","Or pin redirectUri explicitly in the provider options for determinism","Test deployment config with a startup smoke that constructs the provider","Document that local dev may rely on defaults but hosted deploys cannot"],"tags":["config","workos","oauth","redirect-uri","initialization"],"backgroundTag":"missing-env-var","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}