Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Throw custom Joi Errors #779

Closed
eightyfive opened this issue Nov 27, 2015 · 13 comments
Closed

Throw custom Joi Errors #779

eightyfive opened this issue Nov 27, 2015 · 13 comments
Assignees
Labels
feature New functionality or improvement
Milestone

Comments

@eightyfive
Copy link

Hi,

That would be nice if Joi could throw custom Joi Errors:
https://github.com/hapijs/joi/blob/master/lib/errors.js#L140

Something in the fashion of:

/**
 * Custom Joi Error
 */
function JoiError() {
  Error.apply(this, arguments);

  this.details = [];
  // ...
}
JoiError.prototype = Object.create(Error.prototype);
JoiError.prototype.annotate = function () { /* ... */ }


// And later on...
try {
  // Some logic throwing a new JoiError(/* ... */);
  // ...
} catch (err if err instanceof JoiError) {
  // ...
  // Use Joi error details...
} catch (err if err instanceof TypeError) {
  // ...
}

It would make easier catching/narrowing to Joi-related errors in try {} catch (err) {} blocks as illustrated above. I am using koa and that would come very handy. For now I am testing if the thrown err has a details property which is not exactly future-proof nor elegant...

Or may you have a better suggestion to cast Joi errors only?

@eightyfive
Copy link
Author

The conditional catch clauses syntax is not standard.

So my catch example would become:

try {
  // throw new JoiError(/* ... */);
} catch (err) {
  if (err instanceof JoiError) {
    // Use Joi error details...
  } else if (err instanceof TypeError) {
    // ... Etc.
  }
}

@Marsup
Copy link
Collaborator

Marsup commented Nov 27, 2015

What's the benefit from current

try {
  // throw new JoiError(/* ... */);
} catch (err) {
  if (err.name === 'ValidationError') {
    // Use Joi error details...
  } else if (err instanceof TypeError) {
    // ... Etc.
  }
}

?

@eightyfive
Copy link
Author

It's cleaner and more future-proof (vendor specific, object casting)? But this is probably my Java/PHP OOP backgroung telling me that. (I cant help myself but thinking basing logic on string names isn't as strong as using a language strengths)

I missed the 'name' property, so my point isn't as much important anymore.

Thank you for replying!

@Marsup Marsup added the request label Nov 28, 2015
@Marsup Marsup self-assigned this Nov 28, 2015
@Marsup
Copy link
Collaborator

Marsup commented Nov 28, 2015

FWIW, instanceof performance sucks, like half as fast, that might be something you consider if you do it often.

@tejasmanohar
Copy link

👍 for custom error objects. I don't like depending on code, name, etc. due to collision, especially with names as generic as ValidationError. Can we re-open this issue @Marsup @eightyfive?

@macalinao
Copy link

Mongoose also uses ValidationError as the name.

@Marsup
Copy link
Collaborator

Marsup commented Dec 26, 2015

Fair point, I'd go for a Joi.isError, fine for everyone ?

@Marsup Marsup reopened this Dec 26, 2015
@AdriVanHoudt
Copy link
Contributor

Why not isJoi like the isBoom?

@Marsup Marsup added this to the 7.1.0 milestone Dec 26, 2015
@Marsup
Copy link
Collaborator

Marsup commented Dec 26, 2015

Closed by 52c1781.

@Marsup Marsup closed this as completed Dec 26, 2015
@AdriVanHoudt
Copy link
Contributor

👍

@maamun7
Copy link

maamun7 commented Oct 9, 2017

if (error){
            if (error.name === 'ValidationError') {
                let customError = {};

                var spilitedErrorSmg = error.message.split(":");

                for (var key in spilitedErrorSmg) {
                    //Match 'Error' string with each line first 5 characters

                    if (spilitedErrorSmg[key].slice(0, 6).trim() == 'Error') {
                        let trimStr = spilitedErrorSmg[key].replace('Value', '').trim();
                        let spilitedWord = spilitedErrorSmg[key].replace('Value', '').trim().split(/`/)[1];
                        customError[spilitedWord] = trimStr;
                    }
                }
                res.json({msg: error._message, error: customError});
            }
        } else {
            res.json({msg: 'Successfully user registered'});
        }

Error Response:

{
    "msg": "User validation failed",
    "error": {
        "email": "Error, expected `email` to be unique.",
        "mobile": "Error, expected `mobile` to be unique."
    }
}

@uladkasach
Copy link

uladkasach commented May 3, 2019

Out of curiosity, is there any reason not to implement this error as an extension of the Error class? E.g.,

class JoiValidationError extends Error {
...
}

This seems like a more standard approach rather than assigning properties to an instance of the generic error class.

@hueniverse hueniverse added feature New functionality or improvement and removed request labels Sep 19, 2019
@lock
Copy link

lock bot commented Jan 9, 2020

This thread has been automatically locked due to inactivity. Please open a new issue for related bugs or questions following the new issue template instructions.

@lock lock bot locked as resolved and limited conversation to collaborators Jan 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature New functionality or improvement
Projects
None yet
Development

No branches or pull requests

8 participants