'Objection JS & Postgres & Exporess returning 'TypeError: Cannot read property 'isPartial' of null' on many to many relation query

I am trying to relate table named 'products' to another table named 'tags'. I have a many to many table titled 'products_tags'.

When running const product = await Product.relatedQuery('tags').findById(1); I receive the following error:

TypeError: Cannot read property 'isPartial' of null
    at findFirstNonPartialAncestorQuery (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\relations\RelationOwner.js:194:18)
    at Function.createParentReference (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\relations\RelationOwner.js:24:48)
    at QueryBuilder._findOperationFactory (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\model\Model.js:819:25)
    at addFindOperation (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\queryBuilder\QueryBuilder.js:1551:31)
    at addImplicitOperations (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\queryBuilder\QueryBuilder.js:1539:5)
    at beforeExecute (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\queryBuilder\QueryBuilder.js:1439:13)
    at QueryBuilder.execute (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\queryBuilder\QueryBuilder.js:681:13)
    at QueryBuilder.then (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\queryBuilder\QueryBuilder.js:634:26)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)

My product model:

const {Model} = require('objection');

class Product extends Model {
    static get tableName() {
        return 'products'
    }

    static get relationMappings() {
        const Tag = require('./Tag');

        return {
            tags: {
                relation: Model.ManyToManyRelation,
                modelClass: Tag,
                join: {
                    from: 'products.id',
                    through: {
                        from: 'products_tags.product_id',
                        to: 'products_tags.tag_id'
                    },
                    to: 'tags.id'
                }
            }
        }
    }
}

module.exports = Product;

Tags.js

const { Model } = require('objection');

class Tag extends Model {
    static get tableName() {
        return 'tags';
    }

    static get relationMappings() {
        const Product = require ('./Product');

        return {
            products: {
                relation: Model.ManyToManyRelation,
                modelClass: Product,
                join: {
                    from: 'tags.id',
                    through: {
                        from: 'products_tags.tag_id',
                        to: 'products_tags.product_id'
                    },
                    to: 'products.id'
                }
            }
        }
    }
}

module.exports = Tag;

I've made sure the table names and relations are correct, as well as made sure there is matching data in the database. Help is appreciated. Thank you.

edit: here is the migration setup

//...
        knex.schema.createTable('tags', table => {
            table.increments('id').notNullable();
            table.text("name");
            table.boolean("is_deleted").defaultTo(false);
            table.timestamps(true, true);
        }),
        knex.schema.createTable('products', table => {
            table.increments('id').notNullable();
            table.text("name");
            table.text("description");
            table.float("price");
            table.integer('category_id').references('id').inTable('categories');
            table.boolean("can_be_personalized").defaultTo(false);
            table.specificType('images', 'text ARRAY');
            table.boolean("is_deleted").defaultTo(false);
            table.timestamps(true, true);
        }),
        knex.schema.createTable('products_tags', table => {
            table.increments('id').notNullable();
            table.integer('product_id').references('id').inTable('products');
            table.integer('tag_id').references('id').inTable('tags');
            table.boolean("is_deleted").defaultTo(false);
            table.timestamps(true, true);
        }),


Solution 1:[1]

Surely you're not in need of a solution anymore, but to future readers there are three things which can cause this. I just spent the last two and a half hours debugging this same error so in order from easiest to verify up to hardest to verify, they are:

  1. You aren't specifying a primary id for the parent model of your related query. If you're using ModelB.relatedQuery('modelARelation') then you must also call .for(modelBId) or you will get this error. (This is what happened to me because I mixed up req.query and req.params :facepalm:)
ModelB.relatedQuery('modelARelation'); // when run alone, you get this answer

...

const modelBId = req.query.modelBId;
ModelB.relatedQuery('modelARelation').for(modelBId); // works just fine as long as modelBId is properly defined.
  1. Require loops Circular dependency loops. If ModelA relates to ModelB and ModelB relates to ModelA, make sure you are using one of the circular dependency strategies outlined in the docs.
  2. Typos. I hate to say it but if you have gotten this far, it is almost certain that you have typos somewhere. Go eat something or have somebody else look at it. This is actually just good advice generally.

Solution 2:[2]

In my limited experience, this error usually comes when it cannot create the object for whatever reason. Commonly it's an exports issue, or the constructor issue.

Are you sure the filename is correct? You named it Tags.js, but your const Tag = require('./Tag');

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 TheHiggsBroson
Solution 2 user6269972