bitwarden/server · error · BadRequestException

You cannot have a Send with an expiration date greater than

Error message

You cannot have a Send with an expiration date greater than the deletion date. Adjust the expiration date and try again.

What it means

Thrown as BadRequestException (HTTP 400) from SendRequestModel.ValidateEdit() when both ExpirationDate and DeletionDate are set and ExpirationDate > DeletionDate. Logically a Send cannot expire after it is deleted; the server enforces expiration <= deletion.

Source

Thrown at src/Api/Tools/Models/Request/SendRequestModel.cs:242

            if (DeletionDate.Value > now.AddDays(31))
            {
                throw new BadRequestException("You cannot have a Send with a deletion date that far " +
                                              "into the future. Adjust the Deletion Date to a value less than 31 days from now " +
                                              "and try again.");
            }
        }

        if (ExpirationDate.HasValue)
        {
            if (ExpirationDate.Value <= nowPlus1Minute)
            {
                throw new BadRequestException("You cannot have a Send with an expiration date in the past. " +
                                              "Adjust the expiration date and try again.");
            }

            if (DeletionDate.HasValue && ExpirationDate.Value > DeletionDate.Value)
            {
                throw new BadRequestException(
                    "You cannot have a Send with an expiration date greater than the deletion date. " +
                    "Adjust the expiration date and try again.");
            }
        }
    }

    private Send ToSendBase(Send existingSend, ISendAuthorizationService authorizationService)
    {
        existingSend.Key = Key;
        existingSend.ExpirationDate = ExpirationDate;
        existingSend.DeletionDate = DeletionDate!.Value;
        existingSend.MaxAccessCount = MaxAccessCount;
        existingSend.Disabled = Disabled.GetValueOrDefault();
        existingSend.HideEmail = HideEmail.GetValueOrDefault();

        if (existingSend.AuthType == Core.Tools.Enums.AuthType.Password &&
            AuthType == Core.Tools.Enums.AuthType.Password)
        {

View on GitHub (pinned to e93b962371)

Solutions

  1. Ensure ExpirationDate <= DeletionDate (or leave ExpirationDate null).
  2. In the client, derive expiration from deletion or clamp expiration to deletion when the user lowers deletion.
  3. Validate the ordering before submitting the request.
  4. If unsure, omit ExpirationDate so the Send lives until its deletion date.

Example fix

// before
model.DeletionDate = DateTime.UtcNow.AddDays(7);
model.ExpirationDate = DateTime.UtcNow.AddDays(10); // > deletion -> 400

// after
model.DeletionDate = DateTime.UtcNow.AddDays(10);
model.ExpirationDate = DateTime.UtcNow.AddDays(7); // <= deletion
Defensive patterns

Strategy: validation

Validate before calling

// Client: enforce expiration <= deletion
if (model.ExpirationDate.HasValue && model.DeletionDate.HasValue
    && model.ExpirationDate.Value > model.DeletionDate.Value) {
    ShowUser("Expiration date cannot be after the deletion date.");
    return;
}
await client.PostAsync("sends", JsonContent.Create(model));

Type guard

static bool DatesAreConsistent(SendRequestModel m) =>
    !(m.ExpirationDate.HasValue && m.DeletionDate.HasValue
      && m.ExpirationDate.Value > m.DeletionDate.Value);

Prevention

When it happens

Trigger: Any create/edit Send request where ExpirationDate.HasValue && DeletionDate.HasValue && ExpirationDate.Value > DeletionDate.Value.

Common situations: User sets a long expiration but a short deletion; client computes the two independently without cross-checking; editing the deletion date down without adjusting expiration; timezone/unit mismatch between the two fields.

Related errors


AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13). Data as JSON: /api/errors/ad667795f79d576f. Report an issue: GitHub.