sequelize/sequelize · error · Error

Value for "${key}" option must be a string or a boolean, got

Error message

Value for "${key}" option must be a string or a boolean, got ${typeof this.options[key]}

What it means

When `timestamps` is enabled, the constructor iterates createdAt/updatedAt/deletedAt (model-definition.ts:297-302) and asserts each is `undefined`, `string`, or `boolean`. Any other type (number, object, array) throws a plain Error because Sequelize uses these options either to rename a timestamp attribute (string), disable it (false), or leave it as default (undefined/true).

Source

Thrown at packages/core/src/model-definition.ts:299

      } catch (error) {
        throw new BaseError(
          `An error occurred for attribute ${attributeName} on model ${this.modelName}.`,
          { cause: error },
        );
      }

      rawAttributes[attributeName] = rawAttribute;

      if (rawAttribute.field) {
        fieldToColumn();
      }
    }

    // setup names of timestamp attributes
    if (this.options.timestamps) {
      for (const key of ['createdAt', 'updatedAt', 'deletedAt'] as const) {
        if (!['undefined', 'string', 'boolean'].includes(typeof this.options[key])) {
          throw new Error(
            `Value for "${key}" option must be a string or a boolean, got ${typeof this.options[key]}`,
          );
        }

        if (this.options[key] === '') {
          throw new Error(`Value for "${key}" option cannot be an empty string`);
        }
      }

      if (this.options.createdAt !== false) {
        this.timestampAttributeNames.createdAt =
          typeof this.options.createdAt === 'string' ? this.options.createdAt : 'createdAt';

        this.#readOnlyAttributeNames.add(this.timestampAttributeNames.createdAt);
      }

      if (this.options.updatedAt !== false) {
        this.timestampAttributeNames.updatedAt =

View on GitHub (pinned to 7e1deec499)

Solutions

  1. Use a string to rename the attribute, e.g. `createdAt: 'created_at'`.
  2. Use `false` to disable that timestamp, or omit it to keep the default name.
  3. If you need to customize the column name separately, set the option to a string and adjust the attribute's `field`/`columnName`.

Example fix

// before
User.init(attrs, { sequelize, timestamps: true, createdAt: { field: 'created_at' } });

// after
User.init(attrs, { sequelize, timestamps: true, createdAt: 'created_at' });
Defensive patterns

Strategy: validation

Validate before calling

function assertTimestampOpts(opts) {
  if (!opts.timestamps) return;
  for (const key of ['createdAt', 'updatedAt', 'deletedAt']) {
    const v = opts[key];
    if (v !== undefined && typeof v !== 'string' && typeof v !== 'boolean') {
      throw new Error(`${key} must be string|boolean|undefined, got ${typeof v}`);
    }
  }
}
assertTimestampOpts(modelOptions);

Type guard

function isTimestampOptValue(v) {
  return v === undefined || typeof v === 'string' || typeof v === 'boolean';
}

Prevention

When it happens

Trigger: Passing `{ timestamps: true, createdAt: 1 }`, `{ createdAt: { field: 'ca' } }`, or any non-string/non-boolean value for a timestamp option.

Common situations: Typo where a column-name string is replaced by a number; passing a config object instead of a string; misreading the API and providing `createdAt: 'ca'`-shaped objects.

Related errors


AI-assisted analysis of sequelize/sequelize@7e1deec499 (2026-08-03). Data as JSON: /data/errors/17f8e49e3b26db41.json. Report an issue: GitHub.