Change:
<!-- Do Not Delete This! bugreporttemplate --<!-- Please read our Rules of Conduct: --<!-- Please search existing issues to avoid creating duplicates. --<!-- Also please test using the latest insiders build to make sure your issue has not already been fixed: --<!-- Use Help Report Issue to prefill these. --I'm unsure how I got into this state, but I can't close VS Code or reload the window. Stack sohwn when I try to exit:
I cannot explain this, it seems the editor tabs model think there is an editor that does not exist anymore. Needs steps to get any further.
Upon second thought, this can maybe happen if an editor fails to serialize on shutdown. Given we have quite a few new editors, maybe this happens more often now. Marking as candidate to look into and guard against this condition.
Yea, if I recall correctly this happened after I had been playing around with notebooks/custom editors in that window.
if you can try to reproduce, it would still be great to have steps
I have a feeling this could well be notebooks given how the always returns data but the may not. //cc to check if that is a problem. If you know for a fact that you cannot serialize the notebook, please already signal that by returning from the method.
this, I guess we just need to return !(input instanceof NotebookEditorInput)`?
To clarify: it is perfectly valid to return in either of the 2 methods. I pushed a fix to handle this properly on my end. I just wanted to point out that it is always better to return early (from the ) to reduce the data we store in SQLite.
But my that the notebook editor input factory is only called with "my" inputs is valid, right? Or should I assume that it is called with any kind of input and return undefined then?
yeah that assumption is right, you will only be called for inputs you register the factory for.
I don't think anyone has a consistent repro for this, so I will mark it as verified unless I run into it again.

Discussion:
return null; })); <del> this.mru = data.mru.map(i => this.editors[i]); </del> <ins> this.mru = coalesce(data.mru.map(i => this.editors[i])); </ins> this.active = this.mru[0];

class TestEditorInputFactory implements IEditorInputFactory { <ins> static disableSerialize = false; static disableDeserialize = false; </ins> canSerialize(editorInput: EditorInput): boolean { return true; } <del> serialize(editorInput: EditorInput): string { </del> <ins> serialize(editorInput: EditorInput): string | undefined { if (TestEditorInputFactory.disableSerialize) { return undefined; } </ins> let testEditorInput = <TestEditorInput>editorInput; let testInput: ISerializedTestInput = { id: testEditorInput.id

return JSON.stringify(testInput); } <del> deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): EditorInput { </del> <ins> deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): EditorInput | undefined { if (TestEditorInputFactory.disableDeserialize) { return undefined; } </ins> let testInput: ISerializedTestInput = JSON.parse(serializedEditorInput); return new TestEditorInput(testInput.id);

let disposables: IDisposable[] = []; setup(() => { <ins> TestEditorInputFactory.disableSerialize = false; TestEditorInputFactory.disableDeserialize = false; </ins> disposables.push(Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).registerEditorInputFactory('testEditorInputForGroups', TestEditorInputFactory)); });

const input2 = input(); const input3 = input(); <del> // Pinned and Active </del> <ins> // Case 1: inputs can be serialized and deserialized </ins> group.openEditor(input1, { pinned: true, active: true }); group.openEditor(input2, { pinned: true, active: true }); group.openEditor(input3, { pinned: false, active: true }); <del> const deserialized = createGroup(group.serialize()); </del> <ins> let deserialized = createGroup(group.serialize()); </ins> assert.equal(group.id, deserialized.id); assert.equal(deserialized.count, 3); <ins> assert.equal(deserialized.getEditors(EditorsOrder.SEQUENTIAL).length, 3); assert.equal(deserialized.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 3); </ins> assert.equal(deserialized.isPinned(input1), true); assert.equal(deserialized.isPinned(input2), true); assert.equal(deserialized.isPinned(input3), false); assert.equal(deserialized.isActive(input3), true); <ins> // Case 2: inputs cannot be serialized TestEditorInputFactory.disableSerialize = true; deserialized = createGroup(group.serialize()); assert.equal(group.id, deserialized.id); assert.equal(deserialized.count, 0); assert.equal(deserialized.getEditors(EditorsOrder.SEQUENTIAL).length, 0); assert.equal(deserialized.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 0); // Case 3: inputs cannot be deserialized TestEditorInputFactory.disableSerialize = false; TestEditorInputFactory.disableDeserialize = true; deserialized = createGroup(group.serialize()); assert.equal(group.id, deserialized.id); assert.equal(deserialized.count, 0); assert.equal(deserialized.getEditors(EditorsOrder.SEQUENTIAL).length, 0); assert.equal(deserialized.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 0); </ins> }); test('One Editor', function () {