bitwarden/server · error · BadRequestException

Invalid lastKnownRevisionDate format.

Error message

Invalid lastKnownRevisionDate format.

What it means

Thrown by GetLastKnownRevisionDateFromForm when the 'lastKnownRevisionDate' form field is present but cannot be parsed by DateTime.TryParse with CultureInfo.InvariantCulture and DateTimeStyles.RoundtripKind. This field is used for optimistic concurrency — the server compares it against the cipher's actual revision date to detect stale edits. The expected format is ISO 8601 roundtrip (e.g., 2024-01-15T10:30:00.0000000Z).

Source

Thrown at src/Api/Vault/Controllers/CiphersController.cs:1681

    private async Task<CipherOrganizationDetails> GetByIdAsyncAdmin(Guid cipherId)
    {
        return await _cipherRepository.GetOrganizationDetailsByIdAsync(cipherId);
    }

    private async Task<CipherDetails> GetByIdAsync(Guid cipherId, Guid userId)
    {
        return await _cipherRepository.GetByIdAsync(cipherId, userId);
    }

    private DateTime? GetLastKnownRevisionDateFromForm()
    {
        DateTime? lastKnownRevisionDate = null;
        if (Request.Form.TryGetValue("lastKnownRevisionDate", out var dateValue))
        {
            if (!DateTime.TryParse(dateValue, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var parsedDate))
            {
                throw new BadRequestException("Invalid lastKnownRevisionDate format.");
            }
            lastKnownRevisionDate = parsedDate;
        }

        return lastKnownRevisionDate;
    }
#nullable enable

    private async Task<OrganizationAbility?> GetOrganizationAbilityAsync(CipherDetails cipher)
    {
        if (cipher.OrganizationId.HasValue)
        {
            return await _organizationAbilityCacheService.GetOrganizationAbilityAsync(cipher.OrganizationId.Value);
        }
        return null;
    }

    private static OrganizationAbility? GetOrganizationAbility(CipherDetails cipher, IDictionary<Guid, OrganizationAbility> organizationAbilities) =>

View on GitHub (pinned to e93b962371)

Solutions

  1. Send the date in ISO 8601 roundtrip format (the 'O' format specifier): e.g., 2024-01-15T10:30:00.0000000Z
  2. On the client, format using DateTime.ToString("O", CultureInfo.InvariantCulture)
  3. Ensure the form field name is exactly 'lastKnownRevisionDate'
  4. Omit the field entirely if you don't have a valid last-known revision date rather than sending an invalid value

Example fix

// before (locale-dependent format, may fail under non-US cultures)
form["lastKnownRevisionDate"] = lastSync.ToString();

// after (ISO 8601 roundtrip, culture-invariant, RoundtripKind-compatible)
form["lastKnownRevisionDate"] = lastSync.ToString("O", CultureInfo.InvariantCulture);
Defensive patterns

Strategy: validation

Validate before calling

// Validate date format before sending
if (!DateTime.TryParse(dateString, CultureInfo.InvariantCulture,
    DateTimeStyles.RoundtripKind, out _))
{
    // Reformat using ISO 8601 roundtrip format
dateString = lastKnownRevisionDate.ToString("O", CultureInfo.InvariantCulture);
}
form["lastKnownRevisionDate"] = dateString;

Prevention

When it happens

Trigger: Sending a date in a locale-specific format (e.g., '15/01/2024' or 'Jan 15, 2024'); sending a Unix timestamp instead of a date string; sending a malformed or empty date value in the form field; the client serializes DateTime using its local culture instead of InvariantCulture.

Common situations: Client running under a non-invariant culture that formats dates differently; a form field populated with a default/placeholder value that isn't a valid date; client library that uses a different DateTime serialization format; testing tools that send raw timestamps.

Related errors


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