Crashed the first time I ran it

I’m not really sure what’s happened here; it seems like Forest couldn’t handle my schema (postgres). I’ve attached a screenshot:

Any thoughts would be much appreciated. I don’t think there’s anything ‘unusual’ about my database.

Hello @chrism2671 :wave:

Thanks for the detailed logs, it really helps out :+1: and welcome to our community :tada::confetti_ball:

May I ask you the content of your clicks model please ?

It looks like the object passed to clicks.belongsTo() at line 69 is not well instanciated. Indeed it looks like the object to which clicks belongs is baddly instanciated (somewhere should find something like DataTypes.ARRAY() with an empty set of values). Pasting the model to which clicks belongs would be helpfull too :+1:

Awaiting your answer,

Steve.

Sure. links has_many clicks.

In actual fact, I don’t really need the clicks table to be available in Forest, so if it’s fatal, I could remove it.

Hello @chrism2671,

I think what @Steve_Bunlon was asking is your clicks model from your admin backend which was freshly generated by Lumber :wink:
Could you please share it?

Thanks!

Ah yep!

// This model was generated by Lumber. However, you remain in control of your models.
// Learn how here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models
module.exports = (sequelize, DataTypes) => {
  const { Sequelize } = sequelize;
  // This section contains the fields of your model, mapped to your table's columns.
  // Learn more here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models#declaring-a-new-field-in-a-model
  const Clicks = sequelize.define('clicks', {
    country: {
      type: DataTypes.STRING,
    },
    remoteIp: {
      type: DataTypes.STRING,
    },
    insertedAt: {
      type: DataTypes.DATE,
      allowNull: false,
    },
    updatedAt: {
      type: DataTypes.DATE,
    },
    browserName: {
      type: DataTypes.STRING,
    },
    platform: {
      type: DataTypes.STRING,
    },
    linkUserId: {
      type: DataTypes.INTEGER,
    },
    destination: {
      type: DataTypes.STRING,
    },
    botName: {
      type: DataTypes.STRING,
    },
    previousClickId: {
      type: DataTypes.INTEGER,
    },
    linkWorkspaceId: {
      type: DataTypes.INTEGER,
    },
    params: {
      type: DataTypes.JSONB,
    },
    referer: {
      type: DataTypes.STRING,
    },
    accuracyRadius: {
      type: DataTypes.INTEGER,
    },
    isp: {
      type: DataTypes.STRING,
    },
    isEuCountry: {
      type: DataTypes.BOOLEAN,
    },
    captchaScore: {
      type: DataTypes.DOUBLE,
    },
  }, {
    tableName: 'clicks',
    underscored: true,
    timestamps: false,
    schema: process.env.DATABASE_SCHEMA,
  });

  // This section contains the relationships for this model. See: https://docs.forestadmin.com/documentation/v/v6/reference-guide/relationships#adding-relationships.
  Clicks.associate = (models) => {
    Clicks.belongsTo(models.links, {
      foreignKey: {
        name: 'linkIdKey',
        field: 'link_id',
      },
      as: 'link',
    });
  };

  return Clicks;
};

Thanks @chrism2671,

My bet is that it is actually your links model that generates this error (not the clicks one).
Could you also share the links model to dig into this?

Thanks for your help :pray:

1 Like

Sure!

// This model was generated by Lumber. However, you remain in control of your models.
// Learn how here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models
module.exports = (sequelize, DataTypes) => {
  const { Sequelize } = sequelize;
  // This section contains the fields of your model, mapped to your table's columns.
  // Learn more here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models#declaring-a-new-field-in-a-model
  const Links = sequelize.define('links', {
    alias: {
      type: DataTypes.STRING,
    },
    url: {
      type: DataTypes.STRING,
    },
    insertedAt: {
      type: DataTypes.DATE,
      allowNull: false,
    },
    updatedAt: {
      type: DataTypes.DATE,
    },
    rules: {
      type: DataTypes.ARRAY(DataTypes.null),
      defaultValue: "ARRAY[]",
    },
    name: {
      type: DataTypes.STRING,
    },
    note: {
      type: DataTypes.STRING,
    },
    headTags: {
      type: DataTypes.STRING,
    },
    linkifyWords: {
      type: DataTypes.STRING,
    },
    enabled: {
      type: DataTypes.BOOLEAN,
      defaultValue: true,
    },
    replacements: {
      type: DataTypes.STRING,
    },
    domain: {
      type: DataTypes.STRING,
    },
    slug: {
      type: DataTypes.STRING,
    },
    bodyTags: {
      type: DataTypes.STRING,
    },
    cloaking: {
      type: DataTypes.BOOLEAN,
      defaultValue: false,
    },
    utmSource: {
      type: DataTypes.STRING,
    },
    utmMedium: {
      type: DataTypes.STRING,
    },
    utmCampaign: {
      type: DataTypes.STRING,
    },
    utmTerm: {
      type: DataTypes.STRING,
    },
    utmContent: {
      type: DataTypes.STRING,
    },
    spam: {
      type: DataTypes.BOOLEAN,
      defaultValue: false,
    },
    deleted: {
      type: DataTypes.BOOLEAN,
      defaultValue: false,
    },
    blockBots: {
      type: DataTypes.BOOLEAN,
      defaultValue: false,
    },
    refererMode: {
      type: DataTypes.INTEGER,
    },
    customReferer: {
      type: DataTypes.STRING,
    },
    clickFraudMode: {
      type: DataTypes.INTEGER,
    },
    ogTitle: {
      type: DataTypes.STRING,
    },
    ogDescription: {
      type: DataTypes.STRING,
    },
    ogImage: {
      type: DataTypes.STRING,
    },
    fbPixelId: {
      type: DataTypes.STRING,
    },
    forwardParams: {
      type: DataTypes.BOOLEAN,
      defaultValue: false,
    },
    gtmId: {
      type: DataTypes.STRING,
    },
    gaTagId: {
      type: DataTypes.STRING,
    },
    ctaName: {
      type: DataTypes.STRING,
    },
    ctaMessage: {
      type: DataTypes.STRING,
    },
    ctaBtnText: {
      type: DataTypes.STRING,
    },
    ctaUrl: {
      type: DataTypes.STRING,
    },
    ctaBgColor: {
      type: DataTypes.STRING,
    },
    ctaBtnTextColor: {
      type: DataTypes.STRING,
    },
    ctaLogo: {
      type: DataTypes.BOOLEAN,
      defaultValue: true,
    },
    ctaTextColor: {
      type: DataTypes.STRING,
    },
    ctaImage: {
      type: DataTypes.STRING,
    },
  }, {
    tableName: 'links',
    underscored: true,
    timestamps: false,
    schema: process.env.DATABASE_SCHEMA,
  });

  // This section contains the relationships for this model. See: https://docs.forestadmin.com/documentation/v/v6/reference-guide/relationships#adding-relationships.
  Links.associate = (models) => {
    Links.belongsTo(models.workspaces, {
      foreignKey: {
        name: 'workspaceIdKey',
        field: 'workspace_id',
      },
      as: 'workspace',
    });
    Links.hasMany(models.conversions, {
      foreignKey: {
        name: 'linkIdKey',
        field: 'link_id',
      },
      as: 'conversions',
    });
    Links.hasMany(models.clicks, {
      foreignKey: {
        name: 'linkIdKey',
        field: 'link_id',
      },
      as: 'clicks',
    });
  };

  return Links;
};
1 Like

Hi @chrism2671 :wave:t3:

Arnaud’s hunch is right, it seems like the rules field is not declared correctly.

Can you try replacing it by this instead :point_down:t3:

    rules: {
      type: DataTypes.ARRAY(DataTypes.STRING),
      defaultValue: [],
    },

For more details on the Sequelize ORM data types, here’s the documentation.

Let me know if this works for you :slight_smile:

It worked! Thank you! I do think that Forest should handle that more cleanly if possible (or at least, raise an error with instructions to solve).

1 Like

Glad it worked @chrism2671 :tada:

You’re absolutely right. However, the combinations of data types/structures & constraints/validations are endless, maybe you can help by sending us a dump of your database or the DDL of that particular table. This way we’ll be able to reproduce and work on a fix for future projects.

Cheers,