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

"CKEditor Unexpected error" wrapper makes errors unreadable #5595

Closed
Reinmar opened this issue Oct 16, 2019 · 17 comments · Fixed by ckeditor/ckeditor5-utils#313
Closed

"CKEditor Unexpected error" wrapper makes errors unreadable #5595

Reinmar opened this issue Oct 16, 2019 · 17 comments · Fixed by ckeditor/ckeditor5-utils#313
Assignees
Labels
status:discussion type:bug This issue reports a buggy (incorrect) behavior.

Comments

@Reinmar
Copy link
Member

Reinmar commented Oct 16, 2019

Good luck analysing where this issue occurred:

image

We need to improve this as this will be a big PITA.

@Reinmar Reinmar added the type:bug This issue reports a buggy (incorrect) behavior. label Oct 16, 2019
@Reinmar Reinmar added this to the iteration 28 milestone Oct 16, 2019
@Reinmar
Copy link
Member Author

Reinmar commented Oct 16, 2019

Those links to sources don't work. Clicking them opens a new tab:

image

@ma2ciek
Copy link
Contributor

ma2ciek commented Oct 16, 2019

Hm. The core of the problem seems to be displaying the \n character as the CKEditorError JSON.stringify( data ) creates \\n from \n. Maybe we can add use something like JSON.stringify( data ).replace( /\\n/g, '\n' ) )? I can also make the beginning more readable.

@Reinmar
Copy link
Member Author

Reinmar commented Oct 16, 2019

Hm... IDK. It requires some tests, but I'd start from checking what we can keep in the error message. Because I don't think we can expect that data.originalMessage will be printed in any reasonable form. Unless... we'd have a special rule in CKEditorError that if data is an instanceof an error, it then gets printed nicely. Because, do we actually need to have data == { originalError: foo }? Can't we have data == foo?

@ma2ciek
Copy link
Contributor

ma2ciek commented Oct 17, 2019

Because, do we actually need to have data == { originalError: foo }? Can't we have data == foo?

We can't have an error instance passed directly, because the JSON.stringify( error ) returns {}, thus I enumerated there the error properties:

{
	originalError: {
		message: err.message,
		stack: err.stack,
		name: err.name
	}
}

Of course, this data could be kept also as such structure:

{
	message: err.message,
	stack: err.stack,
	name: err.name
}

But it won't change anything in case of displaying the error stack properly.

@ma2ciek
Copy link
Contributor

ma2ciek commented Oct 18, 2019

The other thing that comes to my mind is that we can overwrite the stack trace of the CKEditorError with the original error's stack trace as these errors start in the same place.

E.g.:

static rethrowUnexpectedError( err, context ) {
	if ( err.is && err.is( 'CKEditorError' ) ) {
		throw err;
	}

	const ckeditorError = new CKEditorError( 'unexpected-error: Unexpected error occurred.', context, {
		message: err.message,
		name: err.name
	} );

	ckeditorError.stack = err.stack;

	throw ckeditorError;
}

This construction introduces a little bit of magic but it should make the error stack look good and be clickable.

EDIT: Actually we could override the name and message (partially) too, so it will look like the normal error, but we'll gain an ability to restart the editor.

@ma2ciek
Copy link
Contributor

ma2ciek commented Oct 25, 2019

cc @mlewand, what do you think about the proposed solutions?

@ma2ciek
Copy link
Contributor

ma2ciek commented Nov 4, 2019

ping @Reinmar @mlewand, @pjasiun, could you check my proposals in the above comments?

@pjasiun
Copy link

pjasiun commented Nov 5, 2019

I believe that we should forward errors when the editor is built with --debug flag, instead of wrapping them in CKEditorError. I hope it should be enough to have both easy debugging in the debug mode and working watchdog in the productive mode.

@ma2ciek
Copy link
Contributor

ma2ciek commented Nov 6, 2019

I've checked and on Chrome replacing only the error.stack property results in displaying this stack to the console (and only this) when an error occurs:

Screen Shot 2019-11-06 at 09 46 26

@Reinmar
Copy link
Member Author

Reinmar commented Nov 6, 2019

If it works well in all browsers, then I think it's a good idea. If not, I'd do a custom error message getter for cases where error's additional data is an instance of an error.

@ma2ciek
Copy link
Contributor

ma2ciek commented Nov 18, 2019

This replacement, unfortunately, doesn't print the stack trace well on Safari. It works well on Chrome and FF though. On Safari the stack trace is created once the error is thrown, not when the error is created, thus replacing it doesn't change anything.

Comparison of the original errors and the rethrown errors:

Chrome:
Screen Shot 2019-11-18 at 11 21 09

Firefox:
Screen Shot 2019-11-18 at 11 21 28

Safari:
Screen Shot 2019-11-18 at 11 21 48

The original error could be logged, however it doesn't sound like a good solution.

@jodator
Copy link
Contributor

jodator commented Nov 18, 2019

At least it's something better for majority of users :)

@Reinmar
Copy link
Member Author

Reinmar commented Nov 19, 2019

I guess we can change this multiple times – i.e. try with this and then improve if we'll see that it wasn't enough.

Optionally, if you think that the above result is still bad, we can add do it our // if CK_DEBUG comment, as @pjasiun proposed, to disable the rethrow completely in our entire dev env. This way, we'll have no problems during development at all (due to the flag) and the community and us in some specific cases (like debugging something in docs) will have pretty good errors thanks to the first step.

@ma2ciek
Copy link
Contributor

ma2ciek commented Nov 19, 2019

I guess we can change this multiple times – i.e. try with this and then improve if we'll see that it wasn't enough.

Great 👍

Optionally, if you think that the above result is still bad, we can add do it our // if CK_DEBUG comment, as @pjasiun proposed, to disable the rethrow completely in our entire dev env. This way, we'll have no problems during development at all (due to the flag) and the community and us in some specific cases (like debugging something in docs) will have pretty good errors thanks to the first step.

Can we add the // @if CK_DEBUG // throw err; (where err is the original error) at the beginning of the CKEditorError.rethrowUnexpectedError? This way we should handle all possible debugging obstacles connected with rethrowing errors.

@Reinmar
Copy link
Member Author

Reinmar commented Nov 20, 2019

AFAIU rethrowing will still change the stack trace on Safari? That'd be a bummer, but I guess the only alternative would be something like:

		try {
			if ( this._pendingChanges.length === 0 ) {
				// If this is the outermost block, create a new batch and start `_runPendingChanges` execution flow.
				this._pendingChanges.push( { batch: new Batch(), callback } );

				return this._runPendingChanges()[ 0 ];
			} else {
				// If this is not the outermost block, just execute the callback.
				return callback( this._currentWriter );
			}
		} catch ( err ) {
                        // @if CK_DEBUG // throw err;
			CKEditorError.rethrowUnexpectedError( err, this );
		}

But I don't know how the above will differ from what you proposed. Could you show some stack traces that both solutions will produce?

@ma2ciek
Copy link
Contributor

ma2ciek commented Nov 20, 2019

Oh. Now I reread this and this approach doesn't make any sense on Safari. The only way to preserve the original stack trace there would be commenting the try {, and } catch ( err ) { ... } parts. So actually the // @if CK_DEBUG // throw err; doesn't make sense to me.

The result of adding the // @if CK_DEBUG // throw err; part in the catch() is following:
Screen Shot 2019-11-20 at 11 41 26

And this is a problem for all rethrowing mechanisms on Safari, without logging the original error the stack trace is lost 😞

So maybe instead we could do // @if CK_DEBUG // console.error( err ); before rethrowing?

@Reinmar
Copy link
Member Author

Reinmar commented Nov 20, 2019

Dunno. Let's see it live and decide. We're not debugging things on Safari too often anyway, so we could most likely live without this anyway.

Do changes that you think will be fine, let's merge them and if we'll be still complaining then we can think further.

Reinmar added a commit to ckeditor/ckeditor5-core that referenced this issue Nov 25, 2019
Internal: Rethrow original error in try-catch blocks when the `debug=true` mode is on. Part of ckeditor/ckeditor5#5595.
Reinmar added a commit to ckeditor/ckeditor5-engine that referenced this issue Nov 25, 2019
Internal: Rethrow original error in try-catch blocks when the `debug=true` mode is on. Part of ckeditor/ckeditor5#5595.
Reinmar added a commit to ckeditor/ckeditor5-utils that referenced this issue Nov 25, 2019
Fix: Improved error rethrowing by replacing the error stack. Closes ckeditor/ckeditor5#5595.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status:discussion type:bug This issue reports a buggy (incorrect) behavior.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants