Customizing Duplicate Record Error Messages in Directus via a Hook

Hello everyone :waving_hand:

I’m working on a Directus hook extension that intercepts item creation and displays a custom message when a duplicate record is detected.
The goal is to replace the generic SQL error message:

Duplicate entry for key 'unique_xxx'

with something clearer like:

:warning: This course already exists for the selected teacher, subject, and date.


:hammer_and_wrench: Technical Details

I created a custom hook in the following folder:

/extensions/hooks/hooks_log/

Here’s my index.js file:

export default ({ action }, { services, exceptions }) => {
  const { ItemsService } = services;
  const { ServiceUnavailableException } = exceptions;

  action('items.create', async ({ collection, payload }, { database, accountability }) => {
    if (collection !== 'cours') return;

    const { id_enseignant, matiere, date } = payload;
    const coursService = new ItemsService('cours', { database, accountability });

    const existing = await coursService.readByQuery({
      filter: {
        id_enseignant: { _eq: id_enseignant },
        matiere: { _eq: matiere },
        date: { _eq: date },
      },
      limit: 1,
    });

    if (existing.length > 0) {
      throw new ServiceUnavailableException(
        '⚠️ This course already exists for the selected teacher, subject, and date.'
      );
    }
  });
};

And the package.json file:

{
  "name": "hooks_log",
  "version": "1.0.0",
  "type": "module",
  "directus:extension": {
    "type": "hook"
  }
}


:package: Problem Encountered

The hook sometimes doesn’t appear in the “Extensions loaded” list in Directus.

I’d like to understand:

  1. Do I need a src and dist folder for a simple JavaScript-based hook?

  2. Is there a better way to show user-friendly messages in the Directus UI instead of backend error messages?


:folded_hands: Goal

I’m trying to:

  • Create a reliable hook that prevents duplicates before inserting records

  • Display a clear, user-friendly error message

  • Better understand how Directus loads hook extensions

Can you correct me this example?:

This is super-easy to do with a Flow rather than having to make an extension.
If you have a Flow that runs on item creation and set it to type Filter (blocking), you can do a Collection read operation, then use the Throw Error operation to show a user-friendly message if you’ve found a matching existing entry.
The Throw Error operation is fairly new and was added a few versions ago.

Can you correct me this example?:

​In your Read Data, operation, you’ll need to wrap it in a filter:

{
    "filter": {
        "_and": [
            {
                "Ense": {
                    "_eq": "{{ $trigger.payload.Ense }}"
                }
            },
            {
                "activite": {
                    "_eq": "{{ $trigger.payload.activite }}"
                }
            },
            {
                "date_cours": {
                    "_eq": "{{ $trigger.payload.date_cours }}"
                }
            }
        ]
    }
}

I’m not sure if there’s a way of formatting a Condition operation to detect an empty array, so it’s probably best to use a script operation next to determine whether you’ve got an empty array or not:

module.exports = async function(data) {
	return (data.read_data.length>0);
}

then add a conditional operation to check whether that was true or false, then throw your error if true.

Thank you very much for your reply. Could you send me the correct syntax for condition because my script isn’t working properly? It sends me an error message when adding an element: “The following fields contain invalid values: ==: A value is required ==: A value is required.” And my script in the “condition” node is: "{
“==”: [
{ “var”: “steps.check_dup” },

true
]
}
"
Thank you in advance.

Assuming your script operation is called “check_dup”, your condition node is just this:

{
“check_dup”: {
“_eq”: true
}
}

It works correctly when a duplicate exists (the error is thrown as expected),
but when there is no duplicate, Directus shows the following error instead of allowing the record to be created:
The following fields contain invalid values:
check_dup: The value must be true
thanks in advance

i am always waiting your help
thank in advance