fullstackhero/dotnet-starter-kit · error · InvalidOperationException
Origin URL is not configured.
Error message
Origin URL is not configured.
What it means
ForgotPasswordCommandHandler requires the app's configured OriginUrl (used to build the password-reset link embedded in the email). When the Origin options section is missing or OriginUrl is unset/blank, the handler deliberately fails fast with InvalidOperationException instead of sending an email with a null/relative link.
Solutions
- Set OriginUrl in appsettings.json under the Origin section (e.g. "Origin": { "Url": "https://your-host" } per the options binding) or via env var Origin__Url.
- Verify the options are bound at startup: services.Configure<OriginOptions>(config.GetSection(...)) exists in the Identity/API registration.
- Confirm IOptions<OriginOptions>.Value.OriginUrl is a valid absolute URI; fix malformed URLs that fail to parse into Uri.
- Add a startup validation (IValidateOptions or AddOptions().Validate...) so a missing origin is caught at boot, not on first forgot-password call.
Example fix
// before (appsettings.json)
{
"Database": { "ConnectionString": "..." }
}
// after
{
"Origin": {
"Url": "https://api.myapp.com"
}
} Defensive patterns
Strategy: validation
Validate before calling
var origin = originOptions.Value?.OriginUrl?.ToString();
if (string.IsNullOrWhiteSpace(origin))
throw new InvalidOperationException("Origin URL is not configured (check Origin:Url in appsettings / Origin__Url env var)."); Type guard
bool HasOrigin(OriginOptions? o) => Uri.TryCreate(o?.OriginUrl?.ToString(), UriKind.Absolute, out var u) && (u.Scheme is "http" or "https");
Try / catch
try { await mediator.Send(new ForgotPasswordCommand(email)); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Origin URL is not configured")) {
logger.LogError(ex, "Origin not configured");
return Problem(statusCode: 500, title: "Server misconfiguration: origin URL missing");
} Prevention
- Keep an Origin:Url entry in every environment's appsettings.{env}.json.
- Provide Origin__Url as an env var in Docker/K8s deployments.
- Add startup options validation so misconfig fails fast at boot.
- Document required config keys in deployment runbooks.
When it happens
Trigger: Calling POST forgot-password when appsettings has no Origin section, the OriginUrl key is empty, or the strongly-typed options were never bound (e.g. services.Configure<OriginOptions> not registered or section name typo).
Common situations: Deploying to a fresh environment where only Database/ConnectionStrings were copied over; a config refactor renamed OriginUrl; running the API locally without the Origin appsettings block; Docker deployments missing the Origin__OriginUrl env var.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Role store not configured. Ensure .AddRoles
- Failed to generate authenticator key.
- user not found
- error resetting password
- no policy
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/a81171521cfb48da.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Identity/Modules.Identity/Features/v1/Users/ForgotPassword/ForgotPasswordCommandHandler.cs:27
public sealed class ForgotPasswordCommandHandler : ICommandHandler<ForgotPasswordCommand, string>
{
private readonly IUserService _userService;
private readonly IOptions<OriginOptions> _originOptions;
public ForgotPasswordCommandHandler(IUserService userService, IOptions<OriginOptions> originOptions)
{
_userService = userService;
_originOptions = originOptions;
}
public async ValueTask<string> Handle(ForgotPasswordCommand command, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(command);
var origin = _originOptions.Value?.OriginUrl?.ToString();
if (string.IsNullOrWhiteSpace(origin))
{
throw new InvalidOperationException("Origin URL is not configured.");
}
await _userService.ForgotPasswordAsync(command.Email, origin, cancellationToken).ConfigureAwait(false);
return "Password reset email sent.";
}
}View on GitHub (pinned to 3f2959e683)