We are migrating CKEditor issue tracking to GitHub. Please, use GitHub to report any new issues.

The former tracking system (this website) will still be available in the read-only mode. All issues reported in the past will still be available publicly and can be referenced.

Important: we decided not to transfer all the tickets to GitHub, as many of them are not reproducible anymore or simply no longer requested by the community. If the issue you are interested in, can be still reproduced in the latest version of CKEditor, feel free to report it again on GitHub. At the same time please note that issues reported on this website are still taken into consideration when picking up candidates for next milestones.

It's ugly and long. Messages (if not removed during building) are kept in the production ready code. So to avoid bloating it, we log very infrequently. This may need to change due to #11502.

We do not have a fast option to turn this into code that throws to improve testability. The special case here and especially problematic is asynchronous code in which even if we throw an error, there's no way to catch it (OK, there's window.onerror, but that doesn't mute it AFAIK).

What is errorCode? It's not any more a full message. In order to not keep the full strings inside our code base, we will export them to a guide in docs. Error could would be built from location of a source file and some id:

'range-startcontainer'

'mathjax-lib'

'editor-removeplugins'

'selection-fake-reset'

So a class/plugin/module + a message identifier. Then, CKEDITOR.error/warn will log also a link to a guide where all errors are explained. A bit less user friendly, but especially with growing number of messages it will allow us to drop few KB and also improve the messages as they will be able to be longer.

I know that it's controversial because error codes are less useful, but I don't see a much choice for CKEditor 4. To keep long error messages in the code base, so in development version of the editor errors are fully meaningful we would need to:

Agree that we bloat the code with them and keep them also in the production code.

Implement a new feature in the builder which would look for CKEDITOR.warn/error and replace them with shorter calls (hashes of the messages?) as well as produce a documentation for these hashes. Because we would need a guide for them anyway.

The second solution sounds great for CKEditor 5, but not for CKEditor 4. Therefore I proposed this a little bit controversial change.

Behaviour:

CKEDITOR.error()

If CKEDITOR.verbosity == CKEDITOR.VERBOSITY_ERROR, throws a real error with all the details.

If not, then it fires CKEDITOR#log with data.type = error and all the details.

CKEDITOR.warn()

Fires CKEDITOR#log with data.type = warn and all the details.

CKEDITOR#log has a default (low prior) listener which:

If CKEDITOR.verbosity == CKEDITOR.VERBOSITY_NONE, then do nothing.

If type == error, then tries to use console.error() (downgrades to console.log() if the former does not exist)

If type == warn tries to use console.warn() (downgrades to console.log() if the former does not exist).

In both cases, it logs all the details plus a link to documentation (error codes).

I'm afraid that the code (implementation of warn(), error() and #log things) will exceed size of the current messages (although, we'll also save space for window.console && window.console.log() checks), but that's not the point. The difference will not be big and eventually, after we'll add more warnings in the code, then they will indeed reduce the size comparing to the size without them.

But the point of having them is different – how can we log and throw in a controllable way (for us and other developers)?

There is already a devtools plugin, why not have devtools override CKEDITOR.error() and CKEDITOR.warning() to look up the 'long' text and log that? Best of both worlds... The text is there, in the repo, and visible to developers who want it. But it doesn't have to be in the main js file, so it doesn't bloat the source.

Allowing/ensuring that CKEDITOR.error() and CKEDITOR.warn() are overridable also allows users who want to pipe exceptions into their current reporting pipeline (we use Ember and Opbeat, but angular, newrelic and airbrake are other examples).

If you add a lookup to devtools, current plan will provide:

Good defaults

Discoverability for new users

Configurability for regular users

Overridability for advanced users

As the commenter cited on the ticket, my main concern is the addition of CKEDITOR.warn() and CKEDITOR.error()... If it were in my work queue, I'd separate the concerns into two tickets... One to enable global handling of exceptions, and another aimed at balancing exception message size with developer discoverability.

One change that was discussed with Reinmar is that CKEDITOR.error() fires log event even when CKEDITOR.VERBOSITY_ERROR is used. This way, default log event listener will be always able to display additionalData and documentation URL. It will also allow custom listeners to report problems even if errors were thrown.

Do you still think it's worth to use error codes instead of real, short messages?

Yes. It won't necessarily be so important in CKEditor 4 where we do not perform that much validation, so there are few messages in the code and they can be rather short while still being pretty clear. But with complexity of CKEditor 5's data model we will need a better mechanism. First of all, there will be dozens of errors, second of all, they will be many times very complicated. This requires additional explanation, just as you can see in ​Angular.

So for CKEditor 4 I'm for the easiest possible solution right now – using short error codes and a manually maintained, external reference. That's the simplest thing to implement and since CKEditor 4 does not log many messages flaws of this solution can be ignored.

For CKEditor 5 we can go in two (not disjoint) ways:

As proposed by @dustyj-pn – we may have a special plugin which will extend the error codes with proper messages. As a matter of fact, most likely we'll need such a plugin anyway, because we will need additional tools for debugging data model.

But something still have to maintain the list of errors. The plugin does not solve all cases, because from time to time one need to debug something on production (or understand what a thrown error means). So a guide will need to exist. I also guess that we would like to keep details about errors close to the code which throws them, so this means that we will need to process the code to extract those messages from it, remove the details while building and put them into the guide and the dev tools plugin.

Uncaught Error: [$injector:modulerr] Failed to instantiate module xxx due to:
Error: [$injector:nomod] Module 'xxx' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.

Notice, how the minified version does not have a verbose explanation - this string is left out during minification. A seasoned Angular developer usually doesn't need it anyway because all the necessary information is there.

$module - name of the core module that encountered the error(most of the time it's the $injector, which manages dependency injection).

errshortname - id of the error. Usually an acronym of the error message.

<ErrorDescription> - A human-readable error message. Sometimes contains a hint as to what could be wrong. Not present in production.

If possible to obtain, contains a path of dependencies that lead to the problem, e.g:

$resourceaProvider <- $resourcea <- Products <- tpGridDirective

In this example 'tpGridDirective' directive tried to use the 'Products' service which was dependent on a '$resourcea' service, which in turn was not found by the $injector(no $resourceaProvider provider present).

<URLtoDocs> - URL to docs. Usually pretty general, but if there's a core module in the path it may lead to a more specific explanation.

<StackTrace> - Stack trace. Present in production, but not really informative there. In general it's useful only for Angular core developers.

While thinking about the next steps we realised one thing – changing verbosity from "throw" to "log" doesn't make sense as it will change the behaviour significantly. Even backing to some early returns won't help as throwing affects also the outer function calls.

We can define 3 types of problems:

Problems which should immediately kill the application. Such as incorrect CKEDITOR.replace() argument or inability to load some core class or plugin. Those need to throw errors regardless of any setting as they basically mean that the whole application is useless. Of course, these errors should be catchable, but that's outside of CKEditor 4's scope. Note also that we can throw a subclass of the Error type to implement features as Angular has (see comment:13).

The second kind of problems are those which will definitely affect the working of application, but which do not break it. For instance – undefined MathJax path, undefined file upload path, etc. Those issues should log errors, but they should not throw errors. For those we will introduce CKEDITOR.error() which should use console.error().

And the last kind of problems are those which may affect the working of application or which means that something went a bit wrong. Those need CKEDITOR.warn() which should use console.warn().

So we need to alter our initial plan – CKEDITOR.error() should never throw any errors.

Finally, we need a different verbosity setting. In this case the most useful solution will be a binary flag with two values defined:

CKEDITOR.VERBOSITY_WARN (log all warnings)

CKEDITOR.VERBOSITY_ERROR (log all errors)

the default value will be: CKEDITOR.VERBOSITY_WARN + CKEDITOR.VERBOSITY_ERROR. The logging mechanism can be muted by setting verbosity to 0.