Timestamps are signed 32-bit integers, which means the last date available for storage is 19 January 2038.

A user testing Stripe ran into an error where an expiration after 2037 caused a failed database transaction. (#3070494: Fatal error when card expiration is after January 19, 2038.)

How should we handle this in commerce? It's something which will affect all payment gateways. This happens when storing a payment method.

Drupal core issue: #2885413: Timestamp field items are affected by 2038 bug

Issue fork commerce-3073329

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mglaman created an issue. See original summary.

mglaman’s picture

Linking related issues. Looks like there is a warning check for 32bit systems, but the timestamp still does not have changed sizing.

mglaman’s picture

johnpicozzi’s picture

Ran into this error with the stripe module as well. Seems some kind of validation is in order. Does the Credit Card Industry have a standard for how far in the future the expiration date can be? If so could some kind of validation to check against that be added? I'm sure this isn't that easy, just thinking out loud.

fool2’s picture

Also experienced this in testing. I think we should just make a validation for this to avoid the fatal error (have the exp date fail validation instead of trigger the error)

Then when 2038+ is supported we can remove the validation.

fool2’s picture

Category: Task » Bug report

Marking this as a bug because a fatal error is a user interface problem.

simgui8’s picture

I just came accross this testing Stripe.
To prevent friction from wsod (customer typo), and since I don't think we can add validation to Stripe fields, I ended up creating a lame patch that does

if ($timestamp > 2145830400) {
  $timestamp = 2145830400;
}

within setExpiresTime method in the PaymentMethod class.

I'll stick to that until #2885413: Timestamp field items are affected by 2038 bug lands.
Also related: https://www.drupal.org/node/3227494

newaytech’s picture

For the benefit of others landing here - I've today had this happen in a production site. Customer has a debit card with expiry of October 2039 - so these cards are out there... The card payment succeeded with Stripe - then choked in Commerce. Will have to manually place order.

Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[22003]: Numeric value out of range: 1264 Out of range value for column 'expires' at row 1: INSERT INTO "commerce_payment_method"

ivnish’s picture

Version: 8.x-2.x-dev » 3.x-dev
rszrama’s picture

Why don't we just convert this particular field to unsigned? We don't need to support expiration dates before the UNIX epoch began. 🤷‍♂️

jsacksick’s picture

@rszrama: Because we use a "timestamp" field which defines the following schema:

  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition) {
    return [
      'columns' => [
        'value' => [
          'type' => 'int',
        ],
      ],
    ];
  }

As opposed to a regular "integer" which exposes the following schema:

  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition) {
    return [
      'columns' => [
        'value' => [
          'type' => 'int',
          // Expose the 'unsigned' setting in the field item schema.
          'unsigned' => $field_definition->getSetting('unsigned'),
          // Expose the 'size' setting in the field item schema. For instance,
          // supply 'big' as a value to produce a 'bigint' type.
          'size' => $field_definition->getSetting('size'),
        ],
      ],
    ];
  }

It's possible for integer fields to mark the field as "unsigned" from the field definition which is not possible for Timestamp fields.

I wonder if we could fix this from a storage schema class in the meantime, until Drupal core supports setting the unsigned boolean from the field definition.

jsacksick’s picture

Assigned: Unassigned » jsacksick
Priority: Normal » Major

Bumping the priority, will try fixing this today.

jsacksick’s picture

Assigned: jsacksick » Unassigned
Status: Active » Needs review

Tempted to go ahead and merge this as I tested this on a new install and on an existing install successfully.
However, would be great if somebody else could RTBC the change.

jsacksick’s picture

Title: Year 2038 problem: Decide how to handle cards which expire after the year 2037. » Update the commerce_payment_method.expires field to store only unsigned values.

  • jsacksick committed 72fd23c6 on 3.x
    fix: #3073329 Year 2038 problem: Update the commerce_payment_method....
jsacksick’s picture

Status: Needs review » Fixed

Went ahead and merged the MR.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.