{"record":{"id":"1bc391ea14cca434","repo":"windmill-labs/windmill","slug":"drawerconfigs-request-key-label-drawer-is-not","errorCode":null,"errorMessage":"${drawerConfigs[request.key].label} drawer is not ready","messagePattern":"(.+?) drawer is not ready","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/copilot/chat/CreatedResourceActionDrawers.svelte","lineNumber":116,"sourceCode":"\t\treturn current ? `Edit ${drawerConfigs[current.key].label} ${current.path}` : 'Edit trigger'\n\t})\n\n\tasync function getEditor(request: ActiveDrawerState): Promise<EditorHandle | undefined> {\n\t\tawait request.promise\n\t\tawait tick()\n\t\tawait nextAnimationFrame()\n\n\t\tif (activeDrawer?.id !== request.id) {\n\t\t\treturn undefined\n\t\t}\n\n\t\tif (!editor) {\n\t\t\tawait tick()\n\t\t\tawait nextAnimationFrame()\n\t\t}\n\n\t\tif (!editor) {\n\t\t\tthrow new Error(`${drawerConfigs[request.key].label} drawer is not ready`)\n\t\t}\n\t\treturn editor\n\t}\n\n\tasync function openCreatedResource(action: ToolDisplayAction) {\n\t\tif (action.type !== 'open_created_resource') {\n\t\t\treturn\n\t\t}\n\n\t\tif (action.resource === 'resource') {\n\t\t\tawait resourceEditorDrawer?.initEdit(action.path)\n\t\t\treturn\n\t\t}\n\n\t\tif (action.resource === 'variable') {\n\t\t\tawait variableEditor?.editVariable(action.path)\n\t\t\treturn\n\t\t}","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/copilot/chat/CreatedResourceActionDrawers.svelte#L98-L134","documentation":"getEditor in CreatedResourceActionDrawers.svelte waits one tick plus one animation frame for the drawer's editor component to mount, then throws if it is still undefined. The thrown message names the drawer label from drawerConfigs, indicating the drawer UI was asked to open but its editor instance never became available.","triggerScenarios":"openCreatedResource / openDrawer sets a request; getEditor is called and after `await tick()` + `await nextAnimationFrame()` the `editor` variable is still falsy — e.g. the drawer component failed to mount, the request.key has no matching drawerConfig entry rendering an editor, or the drawer was closed synchronously before mounting.","commonSituations":"Race between the AI chat applying a tool action and the drawer's conditional rendering; a key not present in drawerConfigs so no editor is ever created; component torn down mid-await so the editor binding never populates.","solutions":["Verify request.key exists in drawerConfigs and maps to a drawer that renders an editor","Increase/verify the wait: ensure the drawer markup is actually rendered (not behind an {#if} that is still false) before calling getEditor","Wrap the getEditor call in try/catch and surface a retry or close the drawer instead of an unhandled rejection"],"exampleFix":"// before\nconst editor = await getEditor(request)\n// after\nlet editor\ntry {\n  editor = await getEditor(request)\n} catch {\n  sendUserToast('Could not open the editor drawer, please retry', true)\n  return\n}","handlingStrategy":"try-catch","validationCode":"if (!drawerConfigs[request.key]) { sendUserToast('Unknown drawer', true); return }","typeGuard":"function hasDrawer(key: string): key is keyof typeof drawerConfigs { return key in drawerConfigs }","tryCatchPattern":"try { const editor = await getEditor(request) } catch { sendUserToast('Editor failed to open, please retry', true); activeDrawer = undefined }","preventionTips":["Confirm every emitted request.key exists in drawerConfigs","Don't close the drawer synchronously after requesting it","Render the drawer markup unconditionally while a request is pending"],"tags":["svelte","race-condition","ui-drawer"],"backgroundTag":"component-not-mounted","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}