javascriptormprismamigrateseed

Prisma: Unknown argument aliases. Available options are listed in green. How to resolve this issue?


I'm encountering an issue with Prisma where I'm getting the error message "Unknown argument aliases. Available options are listed in green." This error occurs when I try to insert data into a Prisma model with a relation field named aliases. I've checked the Prisma documentation and reviewed my code, but I can't seem to find the source of the problem.

I attempted to insert data into my Prisma model that includes a relationship named "aliases." I expected the data to be successfully inserted into the database. However, I received an error message stating "Unknown argument aliases. Available options are listed in green." I'm puzzled about the cause of this error and would like to understand why it's happening and how to resolve it. Below sources :

schema.prisma

model Language {
  id        Int      @id @default(autoincrement())
  name      String   @unique
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  pastes Paste[] @relation("paste_language")
  aliases LanguageAlias[] @relation("language_alias")
  extensions LanguageExtension[] @relation("language_extension")

  @@map("language")
}

seedLanguage.js

const { languages } = require("@codemirror/language-data");

async function createFakeLanguages(nbLanguages) {
  if (!nbLanguages || typeof nbLanguages !== "number" || nbLanguages < 0) {
    throw new Error('Le paramètre "nbLanguages" doit être un nombre positif.');
  }
  const languageList = [];
  for (let i = 0; i < languages.length && i < nbLanguages; i++) {
    const languageName = languages[i]?.name || "";
    const arrAliases = (languages[i]?.alias || [])
            .filter((alias) => typeof alias === "string")
      .map((alias) => ({ name: alias }));
    const arrExtensions = (languages[i]?.extensions || [])
      .filter((extension) => typeof extension === "string")
      .map((extension) => ({ name: extension }));
    languageList.push({
      name: languageName,      
      aliases: {
        create: arrAliases,
      },
      extensions: {
        create: arrExtensions,
      },
    });
  }

  return languageList;
}

async function seedLanguage(prisma, nbLanguages) {
  try {
    const languageList = await createFakeLanguages(
      nbLanguages
    );
    await prisma.language.createMany({
      data: languageList,
    });
  } catch (e) {
    e.functionName = "seedLanguage";
    throw e;
  }
}

module.exports = seedLanguage;

seed.js (main script)


const { PrismaClient } = require("@prisma/client");
const prisma = new PrismaClient();
const seedLanguage = require("./seedLanguage");

async function runSeeds() {
  try {
    console.log("Starting seed process...");
    if (!prisma.$connect) {
      throw new Error("Prisma client has not been properly initialized.");
    }
    console.log("Executing seedLanguage()...");
    const nbLanguages = 10;
    await seedLanguage(prisma, nbLanguages);
  } catch (e) {
    console.error(
      "Error while executing seed function:",
      e.functionName
    );
    console.error("Error details:", e);
    process.exit(1);
  } finally {
    await prisma.$disconnect();
  }
}

runSeeds();

Solution

  • Documentation of Prisma says : you cannot use the createMany function with nested relations directly. Instead, you should use the create function in a loop to achieve this. Below an example :

    // schema.prisma
    model Language {
      id        Int      @id @default(autoincrement())
      name      String   @unique
      createdAt DateTime @default(now())
      updatedAt DateTime @updatedAt
    
      pastes Paste[] @relation("paste_language")
      aliases LanguageAlias[] @relation("language_alias")
      extensions LanguageExtension[] @relation("language_extension")
    
      @@map("language")
    }
    
    model LanguageAlias {
      id         Int       @id @default(autoincrement())
      alias      String
      languageId Int
      language   Language  @relation("language_alias", fields: [languageId], references: [id])
      @@map("language_alias")
    }
    
    model LanguageExtension {
      id         Int       @id @default(autoincrement())
      extension  String
      languageId Int
      language   Language  @relation("language_extension", fields: [languageId], references: [id])
      @@map("language_extension")
    }
    
    // seedLanguage.js
    
    /**
     * This script directly inserts foreign key data such as "alias" and "extension" into the main table as objects instead of doing so in the alias and extension tables by specifying the languageId.
     * I chose this approach because I find it simpler than linking the data with foreign keys.
     * To achieve this, I use the "create" function where the data is passed since "createMany" does not exist for relationships.
     */
    
    const { languages } = require("@codemirror/language-data");
    
    const defaultLanguages = [
      {
        name: "JavaScript",
        aliases: [{ alias: "JS" }, { alias: "ECMAScript" }],
        extensions: [{ extension: ".js" }, { extension: ".mjs" }],
      },
      {
        name: "Python",
        aliases: [{ alias: "Py" }],
        extensions: [{ extension: ".py" }],
      },
      {
        name: "Java",
        aliases: [{ alias: "JDK" }],
        extensions: [{ extension: ".java" }],
      },
      {
        name: "C++",
        aliases: [{ alias: "CPP" }],
        extensions: [{ extension: ".cpp" }],
      },
      {
        name: "Ruby",
        aliases: [{ alias: "RubyLang" }],
        extensions: [{ extension: ".rb" }],
      },
    ];
    
    async function createFakeLanguages(nbLanguages) {
      if (!nbLanguages || typeof nbLanguages !== "number" || nbLanguages < 0) {
        throw new Error('The "nbLanguages" parameter must be a positive number.');
      }
    
      const languageList = [];
      for (let i = 0; i < languages.length && i < nbLanguages; i++) {
        const languageName = languages[i]?.name || "";
        const arrAliases = (languages[i]?.alias || [])
          .filter((alias) => typeof alias === "string")
          .map((alias) => ({ alias: alias }));
        const arrExtensions = (languages[i]?.extensions || [])
          .filter((extension) => typeof extension === "string")
          .map((extension) => ({ extension: extension }));
    
        languageList.push({
          name: languageName, // generateUniqueName(faker, nameSet),
          aliases: arrAliases, // tableau d'alias
          extensions: arrExtensions, // tableau d'ext
        });
    
      }
      return languageList;
    }
    
    async function seedLanguage(prisma, nbLanguages) {
      try {
        const languageList = await createFakeLanguages(nbLanguages);
        for (const languageData of languageList) {
          // or with predefined data from defaultLanguages : for (const languageData of defaultLanguages)
          const { aliases, extensions, ...language } = languageData;
          const createdLanguage = await prisma.language.create({
            data: {
              ...language,
              aliases: {
                create: aliases,
              },
              extensions: {
                create: extensions,
              },
            },
          });
          console.log(`Created language : ${createdLanguage.name}`);
        }
      } catch (e) {
        e.functionName = "seedLanguage";
        throw e;
      }
    }
    
    module.exports = seedLanguage;